﻿
  :root{
    /* Палитра в духе Google Calendar (Material): светло-серый фон #f8f9fa, белые
       поверхности, синий акцент #1a73e8, тонкие серые разделители #dadce0,
       подсветка выбранного — нежно-синяя #e8f0fe. */
    --bg:#f8f9fa; --panel:#fff; --line:#dadce0; --line2:#e8eaed;
    --text:#3c4043; --muted:#5f6368; --accent:#1a73e8; --accent-d:#1557b0;
    --head:#202124; --row-alt:#f8f9fa; --hover:#f1f3f4;
    --accent-tint:#e8f0fe;                          /* подсветка активного (Google) */
    --radius:8px; --radius-lg:12px; --radius-pill:9999px;
    --shadow-1:0 1px 2px rgba(60,64,67,.28), 0 1px 3px 1px rgba(60,64,67,.13);
    --shadow-2:0 2px 6px 2px rgba(60,64,67,.13), 0 1px 2px rgba(60,64,67,.28);
    /* ===== Fluid-масштаб: плавно подстраивается под ширину окна =====
       На маленьких ноутбуках сжимается, на больших 2K/4K мониторах — растёт.
       (clamp(min, предпочтит. от vw, max)). Меняешь масштаб всего интерфейса
       здесь — отдельные правила ниже опираются на эти переменные. */
    --fs-base: clamp(12px, 0.23vw + 9.5px, 15.5px);   /* базовый шрифт интерфейса */
    --fs-table: clamp(11px, 0.21vw + 8.7px, 14px);    /* шрифт основной таблицы заказов */
    --pad-x: clamp(10px, 1.4vw, 28px);                /* горизонтальные поля шапки/тулбара/таблицы */
    --dash-w: clamp(168px, 13.5vw, 248px);            /* ширина левого сайдбара-дашборда */
    --gap-y: clamp(6px, 0.5vw, 12px);
  }
  *{box-sizing:border-box;margin:0;padding:0;}
  body{font-family:Roboto,"Google Sans Text","Segoe UI",system-ui,-apple-system,Arial,sans-serif;background:var(--bg);color:var(--text);font-size:var(--fs-base);-webkit-font-smoothing:antialiased;}
  /* Индикатор загрузки данных из БД — тонкая Material-полоса вверху экрана
     (неопределённый прогресс, бегущий сегмент). Показывается, пока идёт
     асинхронная подгрузка состояния (файл базы / сервер / смена направления). */
  #loadBar{position:fixed;top:0;left:0;right:0;height:3px;z-index:400;display:none;
    overflow:hidden;pointer-events:none;background:var(--accent-tint);}
  #loadBar.show{display:none;}   /* полоса-индикатор над header скрыта по просьбе */
  #loadBar .loadBarInner{position:absolute;top:0;height:100%;width:40%;left:-40%;
    background:var(--accent);border-radius:0 3px 3px 0;
    animation:loadBarSlide 1.15s cubic-bezier(.65,.05,.36,1) infinite;}
  @keyframes loadBarSlide{0%{left:-40%;width:40%;}55%{width:55%;}100%{left:100%;width:30%;}}
  @media (prefers-reduced-motion:reduce){#loadBar .loadBarInner{animation:none;left:0;width:100%;opacity:.6;}}
  button{font-family:inherit;cursor:pointer;}
  header{background:var(--head);color:#fff;padding:7px var(--pad-x);display:flex;align-items:center;gap:14px;flex-wrap:wrap;box-shadow:0 1px 2px rgba(60,64,67,.18);position:relative;z-index:3;}
  /* Репорт от 20.08.2026 «шрифт в 2 раза меньше»: было clamp(15px,0.4vw+12.5px,21px) —
     заказчик выбрал «до размера кнопок шапки» (13px, чуть крупнее их 12px + вес 600). */
  header h1{font-size:13px;font-weight:600;}
  header h1 img{height:26px;width:auto;display:block;}
  /* Репорты №375/№387: шторка логотипа — выпадающее меню с реестровыми кнопками,
     переехавшими из тулбара. Кнопка ☰ слева от лого; меню — popover под ней. */
  .navMenuBtn{background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.3);color:#fff;
    border-radius:6px;width:30px;height:30px;font-size:16px;line-height:1;cursor:pointer;
    display:flex;align-items:center;justify-content:center;flex:0 0 auto;order:-1;}
  .navMenuBtn:hover{background:rgba(255,255,255,.22);}
  .navMenuDrop{display:none;position:absolute;top:calc(100% + 4px);left:var(--pad-x, 14px);
    z-index:20;background:var(--panel);border:1px solid var(--line);border-radius:10px;
    box-shadow:0 6px 20px rgba(0,0,0,.25);padding:8px;flex-direction:column;gap:4px;min-width:220px;}
  .navMenuDrop.show{display:flex;}
  .navMenuDrop .btn{width:100%;text-align:left;}
  .brand-logo{display:none;}
  .brand-logo svg{display:none;}
  header .sub{color:#94a3b8;font-size:12px;}
  /* Профиль «admin»: элементы для админа помечены .adminOnly и видны только когда
     у <body> есть класс .admin. Репорт №111: скрытый режим (двойной Ctrl) удалён —
     класс ставится по роли авторизованного пользователя (серверный режим) либо
     всегда в файловом режиме без входа (см. setAdminMode в kenguru.js). */
  body:not(.admin) .adminOnly{display:none !important;}
  /* Элементы, относящиеся только к направлению ДКР (видны лишь при body.dir-dkr). */
  body:not(.dir-dkr) .dkrOnly{display:none !important;}
body.dir-dkr .kenOnly{display:none !important;}   /* репорт №469: зеркало .dkrOnly — элементы только для Kenguru */
  /* Зеркало: элементы только для Kenguru (видны, пока НЕТ body.dir-dkr). */
  body.dir-dkr .kenOnly{display:none !important;}
  /* Справочник ГБУ «Жилищник» (#dkrGbuOvl) — секции округов/районов. */
  #dkrGbuBody .gbuOkr{margin:0 0 8px;border:1px solid var(--line);border-radius:10px;overflow:hidden;}
  #dkrGbuBody .gbuOkrHd{display:flex;align-items:center;gap:10px;padding:9px 12px;cursor:pointer;background:var(--panel-2,#f1f5f9);font-weight:700;user-select:none;}
  #dkrGbuBody .gbuOkrHd:hover{background:var(--hover,#e8eef6);}
  #dkrGbuBody .gbuOkrHd .gbuCaret{transition:transform .15s;font-size:11px;color:var(--muted);}
  #dkrGbuBody .gbuOkr.open .gbuOkrHd .gbuCaret{transform:rotate(90deg);}
  #dkrGbuBody .gbuOkrHd .gbuCnt{margin-left:auto;font-weight:500;font-size:12px;color:var(--muted);}
  #dkrGbuBody .gbuOkrBody{display:none;padding:4px 0 6px;}
  #dkrGbuBody .gbuOkr.open .gbuOkrBody{display:block;}
  #dkrGbuBody .gbuRay{padding:6px 14px 6px 16px;border-top:1px solid var(--line);}
  #dkrGbuBody .gbuRay:first-child{border-top:none;}
  #dkrGbuBody .gbuRayName{font-weight:600;font-size:13px;}
  #dkrGbuBody .gbuOrg{font-size:13px;color:var(--text);padding:2px 0 2px 14px;}
  #dkrGbuBody .gbuOrg.gbuMain{color:var(--accent-d,#1d4ed8);}
  #dkrGbuBody .gbuOrg .gbuTag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:8px;font-size:10px;font-weight:600;background:#fef3c7;color:#92400e;vertical-align:middle;}
  #dkrGbuBody .gbuNoHit{padding:18px;text-align:center;color:var(--muted);}
  html.theme-dark #dkrGbuBody .gbuOkrHd{background:var(--panel-2,#1e293b);}
  /* ДКР: поле «Район» в карточке — выпадающий список с поиском (#sectDkrDocs). */
  /* «Закрывающие документы площадки» — сворачиваемая шторка (по умолчанию закрыта) */
  .dkrDocsHd{cursor:pointer;user-select:none;display:flex;align-items:center;gap:7px;}
  .dkrDocsHd .dkrDocsCaret{display:inline-block;font-size:11px;color:var(--muted);transition:transform .15s ease;}
  .dkrDocsSect.open .dkrDocsHd .dkrDocsCaret{transform:rotate(90deg);}
  .dkrDocsBody{display:none;}
  .dkrDocsSect.open .dkrDocsBody{display:block;}
  .dkrRayFld{position:relative;}
  .dkrRayFld .dkrRayBtn{cursor:pointer;}
  .dkrRayFld::after{content:"▾";position:absolute;right:11px;bottom:9px;font-size:11px;color:var(--muted);pointer-events:none;}
  .dkrRayPop{display:none;position:absolute;z-index:40;top:100%;left:0;right:0;margin-top:4px;background:var(--panel);border:1px solid var(--line);border-radius:10px;box-shadow:0 10px 30px rgba(0,0,0,.20);overflow:hidden;}
  .dkrRayPop.open{display:block;}
  .dkrRaySearch{width:100%;box-sizing:border-box;padding:8px 10px;border:none;border-bottom:1px solid var(--line);font:13px inherit;background:var(--panel-2,#f4f7fb);color:var(--text);outline:none;}
  .dkrRayList{max-height:260px;overflow:auto;}
  .dkrRayItem{display:flex;align-items:baseline;gap:8px;padding:7px 11px;cursor:pointer;font-size:13px;}
  .dkrRayItem:hover{background:var(--hover,#eef3f9);}
  .dkrRayItem.cur{background:var(--accent-tint,#e6efff);}
  .dkrRayItem .rr{font-weight:600;}
  .dkrRayItem .oo{margin-left:auto;font-size:11px;color:var(--muted);}
  .dkrRayNone{padding:14px;text-align:center;color:var(--muted);font-size:12px;}
  html.theme-dark .dkrRaySearch{background:var(--panel-2,#1e293b);}
  #syncBadge{margin-left:auto;display:flex;align-items:center;gap:8px;font-size:12px;}
  #syncDot{width:9px;height:9px;border-radius:50%;background:#64748b;}
  #syncDot.on{background:#22c55e;} #syncDot.warn{background:#f59e0b;}
  /* Индикатор «БД подключена»/«локально» и кнопка «Отключить файл» скрыты по просьбе —
     теперь за подключением следит полноэкранный гейт (#dbGateOvl), в шапке это дублирующая
     информация. !important — updateSyncUI() в kenguru.js по-прежнему выставляет им
     className/style.display (текст/логика не тронуты, элементы просто не показываются). */
  #syncDot,#syncText,#syncDisconnect{display:none !important;}
  #syncBtn{background:#334155;color:#fff;border:1px solid #475569;border-radius:6px;padding:6px 11px;font-size:12px;}
  #syncBtn:hover{background:#3f4d63;}
  /* Кнопка переключения темы (🌙/☀) — рядом с индикатором БД. Шапка тёмная в
     обеих темах, поэтому стиль кнопки общий. */
  #themeBtn{background:transparent;color:#cbd5e1;border:1px solid #475569;border-radius:6px;
    width:30px;height:30px;font-size:15px;line-height:1;padding:0;display:inline-flex;
    align-items:center;justify-content:center;flex:0 0 auto;}
  /* Репорт №429: после замены эмодзи 🌙 на текст «Тема» фиксированные 30px не вмещали
     надпись — ширина по содержимому, шрифт как у остальных кнопок шапки. */
  #themeBtn{width:auto;min-width:30px;padding:0 9px;font-size:12.5px;white-space:nowrap;}
  #themeBtn:hover{background:#3f4d63;color:#fff;border-color:#64748b;}
  #themeBtn:active{transform:scale(.94);}
  /* Кнопка «🔄 Обновить с Я.Диска» перенесена в шапку (справа от 🌙). Шапка тёмная в
     обеих темах, поэтому оформляем под header-кнопки, перебивая .btn-классы по специфичности. */
  #syncBadge #paspPickDirBtn, #syncBadge #syncSmart{background:transparent;color:#cbd5e1;border:1px solid #475569;border-radius:6px;
    height:30px;padding:0 10px;font-size:12px;line-height:1;display:inline-flex;align-items:center;gap:5px;
    flex:0 0 auto;white-space:nowrap;box-shadow:none;}
  #syncBadge #paspPickDirBtn:hover, #syncBadge #syncSmart:hover{background:#3f4d63;color:#fff;border-color:#64748b;box-shadow:none;}
  #syncBadge #paspPickDirBtn:active, #syncBadge #syncSmart:active{transform:scale(.96);}
  #syncBadge #paspPickDirBtn:disabled, #syncBadge #syncSmart:disabled{opacity:.6;cursor:default;}
  /* Реестр КС-2 (ДКР): окно «🏗 КС» — список заказов с генерацией акта. */
  #ksRegOvl .modal{max-width:900px;width:94vw;}
  #ksRegOvl table{width:100%;border-collapse:collapse;font-size:13px;}
  #ksRegOvl thead th{background:var(--row-alt);text-align:left;padding:7px 9px;border-bottom:2px solid var(--line);font-weight:600;position:sticky;top:0;z-index:1;}
  #ksRegOvl tbody td{padding:6px 9px;border-bottom:1px solid var(--line);vertical-align:top;}
  #ksRegOvl tbody tr:hover td{background:var(--hover);}
  /* Окно «Инструкция по сайту» (кнопка ❓ в шапке рядом с темой). */
  /* Админ: всплывающие попапы «что изменено» (на несколько секунд, стопкой). */
  #adminPops{position:fixed;right:14px;bottom:14px;z-index:300;display:flex;flex-direction:column;
    gap:8px;align-items:flex-end;pointer-events:none;max-width:min(380px,80vw);}
  #adminPops .adminPop{pointer-events:auto;cursor:pointer;background:var(--panel);color:var(--text);
    border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:9px;
    padding:8px 12px;box-shadow:0 8px 24px rgba(0,0,0,.22);font-size:12.5px;line-height:1.35;
    opacity:0;transform:translateY(8px);transition:opacity .25s ease,transform .25s ease;max-width:100%;}
  #adminPops .adminPop.show{opacity:1;transform:none;}
  #adminPops .adminPop .apTitle{font-weight:700;}
  #adminPops .adminPop .apBody{color:var(--muted);margin-top:2px;white-space:pre-wrap;word-break:break-word;
    max-height:4.6em;overflow:hidden;}
  /* Админ: окно «Консоль» — лог вывода браузера (монопространственный, тёмный). */
  .conLog{font-family:ui-monospace,Consolas,"Cascadia Code",monospace;font-size:12px;line-height:1.45;
    white-space:pre-wrap;word-break:break-word;max-height:70vh;overflow:auto;
    background:#0b1220;color:#cbd5e1;border:1px solid var(--line);border-radius:8px;padding:10px 12px;}
  html.theme-dark .conLog{background:#070b12;}
  .conLog .cl{display:block;padding:1px 0;border-bottom:1px solid rgba(148,163,184,.10);}
  .conLog .cl .clt{color:#64748b;margin-right:8px;}
  .conLog .cl.warn{color:#fbbf24;}
  .conLog .cl.error{color:#f87171;}
  .conLog .cl.info{color:#93c5fd;}
  .conLog .cl.debug{color:#94a3b8;}
  .conLog .clEmpty{color:#64748b;font-style:italic;}
  /* Репорт №781: стили окна «Инструкция по сайту» удалены вместе с самим окном. */
  /* Дашборд — вертикальный список-сайдбар в левой части (рядом с рабочей областью). */
  #layout{display:flex;align-items:stretch;}
  #mainCol{flex:1;min-width:0;display:flex;flex-direction:column;transition:opacity .15s ease;}
  /* Лёгкий кроссфейд контента при переключении Kenguru ⇄ ДКР (см. switchDirection). */
  #mainCol.dirFading{opacity:0;}
  @media (prefers-reduced-motion: reduce){ #mainCol{transition:none;} #mainCol.dirFading{opacity:1;} }
  #dash{display:flex;flex-direction:column;gap:10px;flex:0 0 auto;width:var(--dash-w);
    padding:12px;background:var(--panel);border-right:1px solid var(--line);}
  /* Репорты №160/№162: левый дашборд и правая панель «Документы» ЗАКРЕПЛЕНЫ при
     прокрутке таблицы — липнут к верху окна, длинное содержимое скроллится внутри.
     min-height — чтобы колонка выглядела сплошной; только десктоп (на телефоне
     #layout — колонка, панели в потоке). */
  @media(min-width:601px){
    #dash,#docsMini{position:sticky;top:0;align-self:flex-start;box-sizing:border-box;
      max-height:100vh;max-height:100dvh;min-height:100vh;min-height:100dvh;overflow-y:auto;}
  }
  /* Репорт №665 (2026-08-26, гриллинг): на десктопе ЗАКРЕПЛЕНЫ при прокрутке ещё и
     шапка сайта (header), тулбар (#toolbar + #bulkBar под ним, когда виден) и шапка
     главной таблицы (#tbl thead) — sticky-стек в ОКОННОМ скролле (скролл-контейнер
     не меняется, дашборд/«Документы» выше остаются sticky, просто сдвигаются под
     шапку). Высоты слоёв ДИНАМИЧЕСКИЕ (header и #toolbar — flex-wrap, переносятся на
     2 строки при узком окне; #bulkBar появляется при выделении) — их меряет JS
     (_calSyncHeadHeight + ResizeObserver в kenguru.js) в CSS-переменные --head-h /
     --tb-h / --bulk-h, из которых складывается top каждого следующего слоя.
     z-лестница: header 6 (внутри него шторка .navMenuDrop z20 — раскрывается ВНИЗ
     поверх тулбара) > #toolbar/#bulkBar 4 > thead th 2 (внутри th кнопка ▾ z3).
     Мобильный (≤600px) намеренно не трогаем — там свой скролл-контейнер #wrap и
     дашборд в потоке (решение заказчика). */
  @media(min-width:601px){
    header{position:sticky;top:0;z-index:6;}
    #dash,#docsMini{top:var(--head-h,0px);
      max-height:calc(100dvh - var(--head-h,0px));min-height:calc(100dvh - var(--head-h,0px));}
    #toolbar{position:sticky;top:var(--head-h,0px);z-index:4;}
    #bulkBar{position:sticky;top:calc(var(--head-h,0px) + var(--tb-h,0px));z-index:4;}
    #tbl thead th{top:calc(var(--head-h,0px) + var(--tb-h,0px) + var(--bulk-h,0px));}
    /* Глобальное `thead th.colFilterCell{position:relative}` ниже по файлу перебивало
       sticky у ВСЕХ фильтруемых колонок главной таблицы (липли только Статус/Прогресс/
       Комплексы — «полуприлипание»). Sticky сам является containing block для
       абсолютной кнопки ▾ (.colMenuBtn), relative ей не нужен — см. тот же вывод в
       комментарии у #calGrid thead th. Точечно для #tbl, остальные таблицы не трогаем. */
    #tbl thead th.colFilterCell{position:sticky;}
  }
  #dashChips{display:flex;flex-direction:column;gap:6px;}
  /* Переключатель направления (Kenguru / ДКР) — над списком статусов. */
  #dirSwitch{display:flex;gap:6px;flex-wrap:wrap;}
  #dirSwitch .dirBtn{flex:1;padding:9px 8px;border:1px solid var(--line);background:var(--panel);border-radius:var(--radius-pill);
    cursor:pointer;font-size:13px;font-weight:500;color:var(--muted);white-space:nowrap;
    transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease;}
  #dirSwitch .dirBtn:hover{border-color:transparent;background:var(--hover);}
  #dirSwitch .dirBtn.active{border-color:transparent;background:var(--accent-tint);color:var(--accent-d);font-weight:600;box-shadow:none;}
  /* «📅 Календарь монтажей» — под кнопками направлений, во всю ширину сайдбара.
     Открывает отдельный экран-страницу календаря (не модальное окно); .active —
     когда календарь открыт (выставляется в openCalendar/_calCloseAll). */
  #dirSwitch .calNavBtn{flex:1 1 100%;padding:9px 8px;border:1px solid var(--line);background:var(--panel);
    border-radius:var(--radius-pill);cursor:pointer;font-size:13px;font-weight:500;color:var(--muted);
    white-space:normal;min-width:0;text-align:center;
    transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease;}
  #dirSwitch .calNavBtn:hover{border-color:transparent;background:var(--hover);}
  #dirSwitch .calNavBtn.active{border-color:transparent;background:var(--accent-tint);color:var(--accent-d);font-weight:600;}
  /* Год базы ДКР (2022–2026) — под переключателем направления, только в ДКР. */
  #dirYearSwitch{display:none;gap:4px;margin-top:6px;flex-wrap:wrap;}
  #dirYearSwitch .dirYearBtn{flex:1 1 auto;min-width:42px;padding:6px 4px;border:1px solid var(--line);background:var(--panel);border-radius:var(--radius-pill);
    cursor:pointer;font-size:12px;font-weight:500;color:var(--muted);
    transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease;}
  #dirYearSwitch .dirYearBtn:hover{border-color:transparent;background:var(--hover);}
  #dirYearSwitch .dirYearBtn.active{border-color:transparent;background:var(--accent-tint);color:var(--accent-d);font-weight:600;}
  /* Кнопки-инструменты (Корзина, История) — под списком статусов, во всю ширину. */
  #dashTools{display:flex;flex-direction:column;gap:6px;padding-top:10px;border-top:1px solid var(--line);}
  #dashTools .btn{width:100%;text-align:left;padding:8px 12px;font-size:12px;}
  /* Блок «Недавно открытые» (заказы + вкладки) — под кнопками-инструментами. */
  #recentBox{display:flex;flex-direction:column;gap:6px;padding-top:10px;border-top:1px solid var(--line);}
  #recentHdr{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;
    color:var(--muted);text-transform:uppercase;letter-spacing:.03em;}
  #recentHdr .recentClear{margin-left:auto;font-size:10px;font-weight:500;color:var(--muted);
    cursor:pointer;text-transform:none;letter-spacing:0;}
  #recentHdr .recentClear:hover{color:var(--accent);text-decoration:underline;}
  #recentList{display:flex;flex-direction:column;gap:3px;}
  .recentItem{display:flex;align-items:center;gap:7px;padding:5px 8px;border:1px solid transparent;
    border-radius:7px;cursor:pointer;font-size:12px;transition:.12s;min-width:0;}
  .recentItem:hover{border-color:var(--accent);background:var(--hover);}
  .recentItem .ri-ic{flex:0 0 auto;font-size:13px;line-height:1;}
  .recentItem .ri-tx{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .recentItem .ri-kind{flex:0 0 auto;font-size:9px;color:var(--muted);text-transform:uppercase;letter-spacing:.02em;}
  #recentEmpty{font-size:11px;color:var(--muted);font-style:italic;padding:2px;line-height:1.35;}
  .chip{position:relative;border:1px solid var(--line);background:var(--panel);border-radius:var(--radius-lg);
    padding:8px 10px 8px 15px;display:flex;flex-direction:row;align-items:center;gap:10px;
    transition:.12s;cursor:pointer;}
  .chip:hover{border-color:transparent;background:var(--hover);box-shadow:var(--shadow-1);}
  .chip.active{border-color:transparent;background:var(--accent-tint);box-shadow:inset 0 0 0 1px var(--accent);}
  .chip .n{font-size:18px;font-weight:700;min-width:30px;text-align:right;flex:0 0 auto;font-variant-numeric:tabular-nums;}
  .chip .l{font-size:12px;color:var(--muted);white-space:normal;line-height:1.25;flex:1;}
  .chip .bar{position:absolute;left:0;top:6px;bottom:6px;width:4px;height:auto;border-radius:0 3px 3px 0;margin:0;}
  #toolbar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:10px var(--pad-x);background:var(--panel);border-bottom:1px solid var(--line);}
  #toolbar input[type=text]{padding:8px 14px;border:1px solid var(--line);border-radius:var(--radius-pill);font-size:13px;background:var(--panel);}
  #search{width:clamp(200px,26vw,440px);}
  .btn{border:1px solid var(--line);background:var(--panel);border-radius:var(--radius-pill);padding:8px 16px;font-size:12px;color:var(--text);font-weight:500;}
  .btn:hover{background:var(--hover);border-color:transparent;box-shadow:var(--shadow-1);}
  .btn.primary{background:var(--accent);color:#fff;border-color:var(--accent);box-shadow:var(--shadow-1);}
  .btn.primary:hover{background:var(--accent-d);border-color:var(--accent-d);box-shadow:var(--shadow-2);}
  .btn.sm{padding:5px 12px;font-size:11px;}
  .btn:disabled{opacity:.45;cursor:not-allowed;box-shadow:none;}
  .spacer{flex:1;}
  .count{color:var(--muted);font-size:12px;}
  #bulkBar{display:none;align-items:center;gap:10px;padding:9px 18px;background:#fff7ed;border-bottom:1px solid #fed7aa;font-size:13px;flex-wrap:wrap;}
  #bulkBar b{font-weight:700;color:#9a3412;}
  td.selcell,th.selcell{text-align:center;width:32px;cursor:default;}
  td.selcell input,th.selcell input{width:15px;height:15px;cursor:pointer;}
  tr.selrow{background:#fff7ed !important;}
  tr.grouprow{cursor:default;}
  tr.grouprow td{background:#1e293b;color:#fff;font-weight:700;font-size:12px;
    padding:7px 10px;border:1px solid #1e293b;letter-spacing:.3px;}
  /* №332: разделы по застройщику во вкладке «➕ Дополнительно» — сворачиваемые */
  tr.dopGroupRow{cursor:pointer;}
  tr.dopGroupRow .grpToggle{display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;margin-right:6px;color:#fff;user-select:none;}
  /* №326: заявки «Приёмка» (ДКР) */
  .priemkiRow{border:1px solid var(--line);border-radius:8px;padding:9px 12px;margin-bottom:8px;background:var(--panel);}
  .priemkiRow.done{opacity:.62;}
  .priemkiDesc{font-weight:600;font-size:13.5px;}
  .priemkiDates{color:var(--muted);font-size:12px;margin-top:3px;}
  .priemkiRowBtns{display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap;}
  .priemkiStSw{display:inline-flex;gap:4px;}
  /* №347/№349: примечания + миниатюра скриншота в строке заявки */
  .priemkiNote{color:var(--text);font-size:12.5px;margin-top:5px;white-space:pre-wrap;word-break:break-word;}
  .priemkiShotThumb{display:block;max-width:160px;max-height:100px;border-radius:6px;border:1px solid var(--line);margin-top:6px;cursor:zoom-in;}
  tr.grouprow:hover td{background:#1e293b;}
  /* Подраздел внизу вкладки «Расстановка отсутствует»: расстановка отмечена, но ГП нет.
     Эти заказы намеренно не попадают в дашборд (чип). Цвет — как у чипа (#9333ea). */
  tr.rasstNogpHdr td{background:#9333ea;color:#fff;font-weight:700;font-size:12px;
    padding:7px 10px;border:1px solid #9333ea;letter-spacing:.3px;}
  tr.rasstNogpHdr:hover td{background:#9333ea;}
  tr.rasstNogpRow{cursor:pointer;}
  tr.rasstNogpRow td{background:#faf5ff;border-bottom:1px solid var(--line2);padding:6px 10px;}
  tr.rasstNogpRow:hover td{background:#f3e8ff;}
  html.theme-dark tr.rasstNogpRow td{background:#241b33;}
  html.theme-dark tr.rasstNogpRow:hover td{background:#2e2240;}
  #wrap{padding:0 var(--pad-x) 60px;}
  table{border-collapse:collapse;width:100%;background:var(--panel);font-size:var(--fs-table);}
  thead th{background:var(--row-alt);color:var(--muted);border:1px solid var(--line);padding:8px;text-align:left;font-weight:500;position:sticky;top:0;z-index:2;cursor:pointer;white-space:nowrap;user-select:none;}
  thead th .arr{color:var(--accent);font-size:10px;}
  thead tr.filters th{position:sticky;top:31px;background:var(--bg);padding:3px;cursor:default;}
  thead tr.filters input{width:100%;border:1px solid var(--line);border-radius:4px;padding:4px 6px;font-size:11px;}
  /* поиск с inline-кнопкой очистки × */
  .searchInputWrap{position:relative;display:inline-flex;align-items:center;}
  .searchInputWrap > input{padding-right:24px !important;width:100%;}
  /* внутри flex-контейнеров обёртка должна тянуться так же, как тянулся бы input */
  .catbar > .searchInputWrap{flex:1;min-width:150px;}
  #toolbar > .searchInputWrap{flex:0 0 auto;}
  /* репорт №377: «Сбросить всё» теперь физически внутри обёртки поиска (см. kenguru.js) */
  #toolbar > .searchInputWrap > input{width:auto;flex:1 1 auto;min-width:80px;}
  #toolbar > .searchInputWrap > #resetAllLink{flex:0 0 auto;white-space:nowrap;padding:0 8px 0 6px;}
  .searchInputWrap > .searchClear{position:absolute;right:6px;top:50%;transform:translateY(-50%);
    width:18px;height:18px;line-height:16px;text-align:center;border-radius:50%;background:#cbd5e1;
    color:#fff;font-size:12px;cursor:pointer;display:none;user-select:none;font-weight:700;
    font-family:Arial,sans-serif;}
  .searchInputWrap > .searchClear:hover{background:#94a3b8;}
  .searchInputWrap.has-value > .searchClear{display:block;}
  /* «Сбросить все» — компактная ссылка рядом с глобальным поиском */
  #resetAllLink{font-size:11px;color:var(--muted);cursor:pointer;text-decoration:underline;
    text-decoration-style:dotted;user-select:none;padding:0 4px;}
  #resetAllLink:hover{color:var(--accent);}
  /* фильтр под заголовком колонки, всплывающий при наведении */
  thead th.colFilterCell{position:relative;}
  thead th.colFilterCell .colFilterBox{
    position:absolute;top:100%;left:0;right:0;z-index:5;padding:6px;background:#fff;
    border:1px solid var(--line);border-top:none;box-shadow:0 4px 8px rgba(0,0,0,.08);
    display:none;cursor:default;}
  thead th.colFilterCell.show .colFilterBox,
  thead th.colFilterCell .colFilterBox.show{display:block;}
  thead th.colFilterCell .colFilterBox input{width:100%;font-size:11px;padding:5px 24px 5px 8px;
    border:1px solid var(--line);border-radius:4px;font-family:inherit;}
  thead th.colFilterCell .colFilterBox .searchInputWrap{display:flex;width:100%;}
  thead th.colFilterCell.has-filter{background:#eaf2ff;}
  /* === Меню фильтра/сортировки столбца (Excel-стиль) — общее для ВСЕХ таблиц ===
     Кнопка ▾ всплывает при наведении на заголовок столбца и открывает компактное
     плавающее меню (#colMenu в body): сортировка + поиск по содержимому + чекбоксы
     значений. Состояние активного фильтра показывает сама кнопка ▾. */
  thead th.colFilterCell{padding-right:22px;}
  thead th.colFilterCell.has-filter::after{display:none;}
  thead th.colFilterCell .colMenuBtn{
    position:absolute;top:50%;right:4px;transform:translateY(-50%);
    width:16px;height:16px;padding:0;margin:0;line-height:14px;
    border:1px solid var(--line);border-radius:3px;background:var(--panel);
    color:var(--muted);font-size:9px;text-align:center;cursor:pointer;
    opacity:0;transition:opacity .12s;z-index:3;}
  thead th.colFilterCell:hover .colMenuBtn,
  thead th.colFilterCell.has-filter .colMenuBtn,
  thead th.colFilterCell .colMenuBtn.open{opacity:1;}
  thead th.colFilterCell .colMenuBtn:hover{border-color:var(--accent);color:var(--accent);}
  thead th.colFilterCell.has-filter .colMenuBtn{border-color:var(--accent);color:#fff;background:var(--accent);}
  #colMenu{position:fixed;z-index:120;width:210px;max-height:calc(100vh - 16px);background:var(--panel);
    border:1px solid var(--line);border-radius:7px;box-shadow:0 8px 24px rgba(15,23,42,.18);
    font-size:12px;color:var(--text);display:none;flex-direction:column;overflow:hidden;user-select:none;}
  #colMenu.show{display:flex;}   /* flex-колонка: список ужимается, кнопки ОК/Отмена всегда видны */
  #colMenu .cmItem{display:flex;align-items:center;gap:7px;padding:6px 10px;cursor:pointer;white-space:nowrap;}
  #colMenu .cmItem:hover{background:var(--hover);}
  #colMenu .cmItem .ic{width:13px;text-align:center;color:var(--accent);font-size:10px;flex:0 0 auto;}
  #colMenu .cmSep{height:1px;background:var(--line);margin:2px 0;}
  #colMenu .cmSearch{padding:7px 8px 6px;}
  #colMenu .cmSearch input{width:100%;box-sizing:border-box;padding:5px 8px;font-size:12px;
    border:1px solid var(--line);border-radius:4px;font-family:inherit;background:var(--panel);color:var(--text);}
  #colMenu .cmList{flex:1 1 auto;min-height:0;max-height:200px;overflow:auto;border-top:1px solid var(--line);}
  #colMenu .cmRow{display:flex;align-items:center;gap:7px;padding:4px 10px;cursor:pointer;margin:0;}
  #colMenu .cmRow:hover{background:var(--hover);}
  #colMenu .cmRow input{margin:0;flex:0 0 auto;}
  #colMenu .cmRow span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  #colMenu .cmRow.all{font-weight:600;border-bottom:1px solid var(--line2);position:sticky;top:0;background:var(--panel);}
  #colMenu .cmRow.empty-lbl span{color:var(--muted);font-style:italic;}
  #colMenu .cmEmpty{padding:8px 10px;color:var(--muted);}
  #colMenu .cmFoot{display:flex;gap:6px;justify-content:flex-end;padding:7px 8px;border-top:1px solid var(--line);}
  #colMenu .cmFoot button{padding:4px 12px;font-size:12px;border-radius:5px;cursor:pointer;
    border:1px solid var(--line);background:var(--panel);color:var(--text);font-family:inherit;}
  #colMenu .cmFoot button.ok{background:var(--accent);border-color:var(--accent);color:#fff;}
  #colMenu .cmFoot button.ok:hover{background:var(--accent-d);}
  tbody td{border:1px solid var(--line2);padding:6px 8px;vertical-align:top;}
  #tbody td{padding:3px 8px;}
  tbody tr:nth-child(even){background:var(--row-alt);}
  tbody tr:hover{background:var(--hover);cursor:pointer;}
  td.num{font-weight:600;color:var(--accent);white-space:nowrap;}
  td.wrapcell{max-width:230px;overflow-wrap:break-word;word-break:break-word;}
  /* Репорт №565: строго однострочная ячейка (напр. «Адрес») — обрезка многоточием,
     полный текст — в title. table-layout:fixed у #tbl держит ширину колонки. */
  td.ellcell{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:0;}
  /* Репорт №789 (2026-09-06): раскрытие адреса на месте УДАЛЕНО целиком (класс
     .ellExpand и его правило) — обратный разворот репортов №728/№749. Ячейка
     «Адрес» снова ведёт себя как остальные ячейки строки: любой клик открывает
     карточку заказа; полный адрес — в title при наведении, а ширину колонки можно
     подогнать двойным кликом по её ручке (репорт №777). */
  /* ===== Адаптивная таблица заказов ====================================
     Колонки переносят длинный текст и подстраивают ширину под окно. Низко-
     приоритетные колонки прячутся классами .h-<ключ> на #tbl — их включает JS
     (applyResponsiveColumns), когда таблица не помещается в рабочую область.
     Горизонтальный скролл (#wrap{overflow-x}) остаётся лишь крайним резервом,
     если не влезают даже ключевые колонки (№, Наименование, Статус, даты). */
  /* table-layout:fixed — раскладка по ширинам КОЛОНОК (th заданы style.width=col.w,
     selcell=32px), без замеров содержимого каждой ячейки. Layout таблицы на ~160
     строк падает со 130+ мс до O(числа_строк): браузер больше не меряет контент
     каждой ячейки для расчёта ширин. applyResponsiveColumns и так держит сумму
     видимых ширин ≤ рабочей области, поэтому перенос текста (wrapcell) сохраняется,
     а переполнения нет. Scoped на #tbl — прочие таблицы остаются на auto. */
  /* ═══ Репорт №777: «честная» ширина колонок ═══
     Было: общее правило table{width:100%} + table-layout:fixed. При fixed-раскладке, когда
     сумма заданных ширин МЕНЬШЕ ширины таблицы, браузер раскидывает остаток ПРОПОРЦИОНАЛЬНО
     по всем колонкам — на мониторе 1600px набор Kenguru по умолчанию (886px) растягивался
     почти вдвое, и ширина, выставленная мышью, «плыла», уводя за собой соседей.
     Стало: width:max-content — таблица ровно по сумме заданных ширин, каждая колонка своей
     ширины, справа остаётся пустое место (как в Excel). Отдельный столбец-доборщик для
     этого не нужен: пустая область — просто фон страницы, поэтому она не наследует ни рамки
     таблицы, ни клик по строке «открыть заказ».
     Не влезает в окно — работает обычная горизонтальная прокрутка страницы (та же, что и
     раньше при широких наборах колонок), а applyResponsiveColumns по-прежнему прячет
     низкоприоритетные колонки, чтобы до прокрутки доходило редко. */
  #tbl{table-layout:fixed;width:max-content;}
  #tbl.h-kontakt  .col-kontakt,
  #tbl.h-dogovor  .col-dogovor,
  #tbl.h-adres    .col-adres,
  #tbl.h-manager  .col-manager,
  #tbl.h-zastroy  .col-zastroy,
  #tbl.h-date     .col-date,
  #tbl.h-reqs     .col-reqs,
  #tbl.h-progress .col-progress,
  /* Репорт №779: новые колонки под поля карточки заказа — у КАЖДОЙ с prio>0 обязана
     быть своя пара .h-<ключ>, иначе applyResponsiveColumns «спрячет» её только в своём
     счётчике ширин, а на экране колонка останется и таблица переполнится. */
  #tbl.h-region        .col-region,
  #tbl.h-contractor    .col-contractor,
  #tbl.h-carrier       .col-carrier,
  #tbl.h-crm           .col-crm,
  #tbl.h-note          .col-note,
  #tbl.h-mountDoneDate .col-mountDoneDate,
  #tbl.h-shipDoneDate  .col-shipDoneDate,
  #tbl.h-callDate      .col-callDate,
  #tbl.h-cx       .col-cx{display:none;}
  /* Репорт №777: после «честной» ширины подпись узкого заголовка больше не маскируется
     растягиванием — обрезаем многоточием вместо наезда на соседнюю колонку. */
  #headRow th.colHdrTh{overflow:hidden;text-overflow:ellipsis;}
  /* ═══ Репорт №707: перетаскивание порядка + ручка ширины колонок главной таблицы.
     th позиционирован (sticky, №665) — абсолютная ручка у правого края работает.
     ═══ Репорт №777 ═══ Ручка ПЕРЕЕХАЛА внутрь своей колонки: было right:-4px;width:8px,
     т.е. половина зоны захвата «навесом» заходила на соседний th — а он sticky со своим
     z-index:2 (отдельный контекст наложения) и рисуется поверх, закрашивая навес
     непрозрачным фоном. Реально кликабельными были ~4px СЛЕВА от границы — отсюда
     жалоба «столбцы не раздвигаются». Теперь right:0;width:9px (целиком внутри своей
     колонки) + отдельная левая половина .colResizerL в СЛЕДУЮЩЕЙ колонке (тянет
     предыдущую) — вместе сплошная зона ~15px поперёк разделителя, как в Excel.
     ::after — постоянно видимая насечка на границе (заказчик: «граница видна и курсор
     col-resize появляется заранее»). */
  #headRow th .colResizer{position:absolute;top:0;right:0;width:9px;height:100%;
    cursor:col-resize;z-index:4;}
  #headRow th .colResizer::after{content:"";position:absolute;right:0;top:15%;bottom:15%;
    width:2px;border-radius:1px;background:var(--line);}
  #headRow th .colResizer:hover{background:rgba(59,130,246,.22);}
  #headRow th .colResizer:hover::after{background:var(--accent);}
  #headRow th .colResizer.colResizerL{right:auto;left:0;width:6px;}
  #headRow th .colResizer.colResizerL::after{display:none;}   /* насечку рисует правая половина */
  /* Кнопка ▾ уходит левее ручки, иначе они перекрывались бы по правому краю th.
     Заскоплено на #headRow: общее правило thead th.colFilterCell{padding-right:22px}
     обслуживает ещё десяток таблиц (журналы/реестры) — их не трогаем. */
  #headRow th.colFilterCell{padding-right:30px;}
  #headRow th.colFilterCell .colMenuBtn{right:12px;}
  #headRow th.colDragging{opacity:.55;}
  #headRow th.colDropL{box-shadow:inset 3px 0 0 #3b82f6;}
  #headRow th.colDropR{box-shadow:inset -3px 0 0 #3b82f6;}
  body.colDragBody{cursor:grabbing !important;user-select:none;}
  /* ===== Кнопка-иконка «копировать» в ячейке наименования.
     Скрыта; появляется при наведении на строку заказа (на сенсорных — всегда). */
  td.nameCell{position:relative;}
  td.nameCell .nameText{display:block;}
  .rowCopyBtn{position:absolute;top:3px;right:3px;display:none;
    align-items:center;justify-content:center;width:22px;height:22px;padding:0;
    border:1px solid var(--line);background:#fff;color:var(--muted);
    border-radius:5px;cursor:pointer;box-shadow:0 1px 4px rgba(15,23,42,.2);}
  .rowCopyBtn svg{width:13px;height:13px;display:block;}
  .rowCopyBtn:hover{color:var(--accent);border-color:var(--accent);background:#fff;}
  .rowCopyBtn:active{transform:translateY(1px);}
  .rowCopyBtn.copied{color:#16a34a;border-color:#16a34a;}
  tbody tr:hover .rowCopyBtn{display:inline-flex;}
  @media(hover:none){.rowCopyBtn{display:inline-flex;}}
  /* №334: та же иконка-кнопка в заголовке заказа docsMini — не absolute (там flex-строка) */
  .dmGroupHd .rowCopyBtn.dmCopyBtn{position:static;display:none;margin-left:auto;flex:0 0 auto;}
  .dmGroupHd:hover .rowCopyBtn.dmCopyBtn{display:inline-flex;}
  @media(hover:none){.dmGroupHd .rowCopyBtn.dmCopyBtn{display:inline-flex;}}
  .badge{display:inline-block;padding:2px 9px;border-radius:11px;font-size:11px;font-weight:600;white-space:nowrap;color:#fff;}
  .pill{display:inline-block;padding:1px 7px;border-radius:9px;font-size:10.5px;font-weight:600;background:#e5e9f0;color:#374151;margin:1px;}
  .prog{font-weight:600;font-size:11px;text-align:center;}
  .progBar{display:flex;align-items:center;gap:6px;}
  .progBar .track{flex:1;height:6px;background:#e5e7eb;border-radius:99px;overflow:hidden;}
  .progBar .fill{height:100%;border-radius:99px;transition:width .25s ease;background:#10b981;}
  .progBar .lbl{font-size:10.5px;color:#475569;font-weight:600;min-width:32px;text-align:right;}
  .progBar.pbEmpty .lbl{color:#9aa1ad;}
  .cxbadge{background:#eef2ff;color:#3730a3;padding:2px 8px;border-radius:10px;font-weight:600;font-size:11px;}
  .empty{text-align:center;padding:40px;color:var(--muted);}
  .ovl{position:fixed;inset:0;background:rgba(32,33,36,.6);display:none;align-items:flex-start;justify-content:center;padding:26px 14px;z-index:50;overflow:auto;overscroll-behavior:contain;}
  .ovl.show{display:flex;}
  /* Гейт «Подключить базу данных» — полностью перекрывает интерфейс (z-index
     выше любого модального окна), пока файл БД не подключён/не активен. */
  .dbGate{position:fixed;inset:0;z-index:99999;background:var(--bg);display:none;align-items:center;justify-content:center;padding:24px;}
  .dbGate.show{display:flex;}
  body:has(.dbGate.show){overflow:hidden;}
  .dbGate .dbGateBox{max-width:440px;text-align:center;}
  .dbGate .dbGateIcon{font-size:42px;line-height:1;margin-bottom:10px;}
  .authPendingIcon{animation:badgePulse 1.4s ease-in-out infinite;}
  .dbGate h2{margin:0 0 10px;font-size:19px;color:var(--text);}
  .dbGate p{margin:0 0 22px;color:var(--muted);font-size:13px;line-height:1.55;}
  .dbGate .btn.primary{font-size:15px;padding:12px 26px;}
  /* 2026-09-14 (P1): экран «Загрузка данных с сервера…» (#srvLoadOvl) — та же коробка
     .dbGate; при сбое связи (класс srvErr) крутилка оранжевая. */
  .srvLoadSpin{width:34px;height:34px;margin:0 auto 16px;border:3px solid var(--line);border-top-color:#3b82f6;border-radius:50%;animation:srvLoadSpin .9s linear infinite;}
  #srvLoadOvl.srvErr .srvLoadSpin{border-top-color:#f59e0b;}
  @keyframes srvLoadSpin{to{transform:rotate(360deg);}}
  /* 2026-09-14 (P1): карточка заказа при открытии сверяется с сервером (GET /api/order) —
     пока ответ не пришёл (не дольше нескольких секунд), поля не принимают ввод, чтобы
     правка шла от актуальной версии заказа. */
  #ovl.srvChecking #mBody,#ovl.srvChecking #mSave{pointer-events:none;opacity:.55;transition:opacity .15s;}
  /* 2026-09-15 (P1 р2, R25): и шапка (дата создания, цвет, «Подзаказы», 📁 — всё, кроме
     заголовка, «Копировать», «Свернуть» и «×»), и «Удалить заказ». Клавиатуру и программный
     фокус закрывает атрибут inert (ставит kenguru.js, _cardSrvCheckSync). */
  #ovl.srvChecking #mDelete,
  #ovl.srvChecking .modal>h2>:not(#mTitle):not(#mCopyTitle):not(#mClose):not(.winMinBtnMark){pointer-events:none;opacity:.55;transition:opacity .15s;}
  /* Гейт входа (#authGateOvl) — та же коробка .dbGate, но с формой логина/регистрации. */
  .authBox .fld{text-align:left;margin-bottom:10px;}
  .authBox .fld label{display:block;font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.3px;margin-bottom:3px;}
  .authBox .fld input{width:100%;box-sizing:border-box;border:1px solid var(--line);border-radius:6px;padding:9px 10px;font-size:14px;font-family:inherit;}
  .authBox .btn.primary{width:100%;box-sizing:border-box;}
  .authErr{color:#dc2626;font-size:12.5px;margin:-4px 0 12px;text-align:left;line-height:1.4;}
  .authSwitch{margin-top:14px;font-size:12.5px;color:var(--muted);}
  .authSwitch a{color:var(--accent);cursor:pointer;text-decoration:underline;}
  #authUserBadge{display:inline-flex;align-items:center;gap:8px;margin-left:8px;}
  #authUserName{font-size:12.5px;color:var(--muted);font-weight:600;}
  .authAdminRow{display:flex;align-items:center;gap:10px;padding:8px 6px;border-bottom:1px solid var(--line);flex-wrap:wrap;}
  .authAdminRow:last-child{border-bottom:none;}
  .authAdminRow .authAFio{flex:1;min-width:160px;font-weight:600;}
  .authAdminRow .authARole{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.3px;}
  /* Репорт №422: онлайн-маячок — есть ли у пользователя ПРЯМО СЕЙЧАС живое SSE-подключение. */
  /* Репорт №447: ПКМ-меню по 3D-модели (Удалить/Дублировать/Повернуть на 90°). */
  #pl3dCtxMenu{position:absolute;z-index:8;background:var(--panel);border:1px solid var(--line);border-radius:8px;
    box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:180px;}
  #pl3dCtxMenu.show{display:block;}
  #pl3dCtxMenu button{display:block;width:100%;text-align:left;padding:7px 10px;border:none;background:none;
    cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
  #pl3dCtxMenu button:hover{background:var(--hover);}
  #pl3dCtxMenu button.danger{color:#dc2626;}
  /* Репорт №787: подпись комплекса под курсором в 3D-режиме схемы расстановки.
     z-index между 3D-холстом (#pl3dWrap, 5) / подсказкой (#plHint, 6) и ПКМ-меню
     (#pl3dCtxMenu, 8); pointer-events:none — плашка не должна перехватывать
     перетаскивание и орбиту. Тёмная полупрозрачная — читается и в светлой, и в
     тёмной теме, на фоне 3D-сцены. */
  #pl3dHoverTip{position:absolute;z-index:7;display:none;pointer-events:none;
    max-width:280px;padding:3px 8px;border-radius:6px;font-size:11px;line-height:1.35;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
    background:rgba(15,23,42,.72);color:#fff;box-shadow:0 2px 8px rgba(0,0,0,.18);}
  .authOnlineDot{flex:0 0 auto;width:9px;height:9px;border-radius:50%;background:#cbd5e1;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);}
  .authOnlineDot.on{background:#22c55e;box-shadow:0 0 0 2px rgba(34,197,94,.2);}
  html.theme-dark .authOnlineDot{background:#475569;}
  html.theme-dark .authOnlineDot.on{background:#22c55e;}
  /* Выпадающий список ролей (репорт bugmscx6ypy0aaf) */
  .authRoleSel{border:1px solid var(--line);border-radius:6px;padding:5px 6px;font-size:12px;background:var(--bg);color:inherit;max-width:210px;}
  /* Репорт №273: роль/сброс пароля/удаление — под иконкой «⚙ Панель управления».
     Репорт №435: раскрытая панель больше НЕ переносится на новую строку — кнопки
     встают в ту же строку справа от ФИО (перенос остаётся только при нехватке
     ширины за счёт flex-wrap самой строки). */
  .authAdminPanel{display:inline-flex;align-items:center;min-width:0;}
  .authAdminPanel summary{list-style:none;cursor:pointer;display:inline-flex;width:fit-content;}
  .authAdminPanel summary::-webkit-details-marker{display:none;}
  .authAdminPanelBody{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap;margin-left:8px;min-width:0;}
  /* Репорт №93: заявки на регистрацию (согласование) + счётчик на кнопке «Пользователи» */
  .authAdminHd{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);padding:12px 6px 4px;border-bottom:1px solid var(--line);}
  .authAdminRow.authPending{background:rgba(245,158,11,.08);}
  .authAdminRow.authPending .authARole{color:#d97706;font-weight:700;}
  #authUsersBtn.authHasPending{background:#fef3c7;border-color:#f59e0b;color:#92400e;font-weight:700;}
  /* Пока открыто любое модальное окно — блокируем прокрутку основного меню под ним
     (overscroll-behavior выше гасит «протекание» скролла на границе списка). */
  body:has(.ovl.show){overflow:hidden;}
  .ovl.lvl2{z-index:60;background:rgba(32,33,36,.5);}
  .modal{background:var(--panel);border-radius:var(--radius-lg);width:clamp(320px,92vw,760px);max-width:100%;box-shadow:0 11px 15px -7px rgba(0,0,0,.2),0 24px 38px 3px rgba(0,0,0,.14),0 9px 46px 8px rgba(0,0,0,.12);}
  /* Репорт №451: футеры окон ЗАКРЕПЛЕНЫ и на десктопе — окно ограничено вьюпортом,
     прокручивается только тело (.mbody), заголовок и футер с кнопками видны всегда
     (та же flex-модель, что давно работает на телефоне; ширины окон не меняются).
     52px = вертикальные отступы .ovl (26px сверху и снизу). */
  @media(min-width:601px){
    .ovl .modal{display:flex;flex-direction:column;max-height:calc(100vh - 52px);max-height:calc(100dvh - 52px);}
    .ovl .modal > h2,.ovl .modal > .mfoot{flex:0 0 auto;}
    .ovl .modal > .mbody{flex:1 1 auto;min-height:0;overflow-y:auto;}
    /* окна с нестандартной разметкой (прокручиваемая зона — не .mbody), как в мобильной ветке;
       #ks2Body/#subOrdList — те же случаи (без .mbody), иначе длинная форма/список вытекали бы
       за нижнюю границу обрезанной по max-height модалки */
    #ksOvl > .modal > #ksBody,#ksRegOvl > .modal > #ksRegBody,
    #ks2Ovl > .modal > #ks2Body,#subOrdOvl > .modal > #subOrdList{flex:1 1 auto;min-height:0;max-height:none!important;overflow-y:auto;}
    /* нижняя панель свёрнутых окон добавляет .ovl отступ 52px — не прячем футер под ней */
    body.has-wintaskbar .ovl .modal{max-height:calc(100vh - 78px);max-height:calc(100dvh - 78px);}
  }
  .modal.wide{width:clamp(320px,93vw,1040px);}
  /* Репорты №125/№131 (мобильная версия): «safe»-центрирование окон. Когда окно
     ШИРЕ вьюпорта (узкий экран телефона), flex justify-content:center выносил его
     левую часть за край .ovl без возможности доскроллить («окно со смещением»,
     «карточка не полностью»). Auto-маргины центрируют так же при свободном месте,
     а при переполнении схлопываются в 0 → окно прижато к левому краю и целиком
     доступно прокруткой .ovl. Спец-режимы (shotOpen/side-panel/win-tile) задают
     свои маргины более специфичными селекторами — их это правило не трогает. */
  .ovl>.modal{margin-left:auto;margin-right:auto;}
  /* ==========================================================================
     «Календарь монтажей» — отдельный экран-страница, НЕ модальное окно.
     Кнопка открытия — в #dirSwitch (сайдбар). Календарь занимает рабочую область
     (справа от сайдбара, ниже шапки сайта): непрозрачный фон, без затемнённой
     подложки и без тайлинга с карточкой. Карточка заказа открывается обычной
     модалкой поверх. Высоту шапки (--head-h) выставляет JS (openCalendar/resize),
     чтобы верх страницы календаря начинался ровно под шапкой сайта. */
  #calOvl{position:fixed;top:var(--head-h,0px);left:var(--dash-w);right:0;bottom:0;
    background:var(--bg);padding:0;z-index:30;display:none;overflow:hidden;align-items:stretch;}
  #calOvl.show{display:flex;flex-direction:column;}
  /* пока календарь открыт — не даём прокручиваться шапке/таблице под ним */
  body:has(#calOvl.show){overflow:hidden;}
  /* «окно» календаря разворачиваем на всю страницу (снимаем рамку/тень модалки) */
  #calOvl .modal,#calOvl .modal.wide{width:auto;max-width:none;margin:0;border-radius:0;
    box-shadow:none;background:var(--bg);flex:1 1 auto;min-width:0;min-height:0;
    display:flex;flex-direction:column;animation:none;}
  #calOvl .mbody{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
    padding:10px clamp(12px,1.4vw,22px);}
  #calOvl #calGrid{flex:1 1 auto;min-height:0;max-height:none;}
  #calOvl .mfoot{flex:0 0 auto;}
  /* на узких экранах сайдбар уходит наверх — календарь занимает всю ширину.
     Репорт от 18.09.2026: экран должен начинаться НИЖЕ ленты #dash (Kenguru/ДКР,
     «Все заказы», проблемные вкладки), а не под неё — иначе эти кнопки становятся
     недостижимы, пока открыт экран-режим (--dash-mob-h — JS, _calSyncHeadHeight). */
  @media(max-width:600px){ #calOvl{left:0;top:calc(var(--head-h,0px) + var(--dash-mob-h,0px));} }
  /* Тайлинг «Календарь монтажей» + карточка заказа (calSqueeze/calOpen, баг-репорт #6):
     календарь сжимается в левую половину экрана, карточка открывается в правой —
     вместо перекрытия. sticky-left у оставшихся колонок пересчитывает JS
     (_calRefreshStickyLeft) — этому правилу достаточно спрятать узкие мета-колонки. */
  #calOvl.calSqueeze{right:50%;}
  #calOvl.calSqueeze #calGrid .col-zayavka,
  #calOvl.calSqueeze #calGrid .col-adres,
  #calOvl.calSqueeze #calGrid .col-manager,
  #calOvl.calSqueeze #calGrid .col-contractor,
  #calOvl.calSqueeze #calGrid .col-carrier,
  #calOvl.calSqueeze #calGrid .col-work{display:none;}
  #ovl.calOpen{left:50%;justify-content:center;padding:26px 1.5vw;}
  #ovl.calOpen .modal.wide{width:96%;max-width:96%;margin:0;}

  /* Репорт №425: «Загрузка файла документации» больше не перекрывает «Мониторинг КД» —
     тайлинг 50/50 по образцу calSqueeze/calOpen выше (оба — обычные .ovl, не спец.
     полноэкранная разметка календаря). kdMonOvl — левая половина, docUploadOvl — правая. */
  #kdMonOvl.kdmSqueeze{right:50%;justify-content:center;padding:26px 1.5vw;}
  #kdMonOvl.kdmSqueeze .modal.wide{width:96%;max-width:96%;margin:0;}
  #docUploadOvl.kdmOpen{left:50%;justify-content:center;padding:26px 1.5vw;}
  #docUploadOvl.kdmOpen .modal{width:96%;max-width:96%;margin:0;}

  /* Репорт №476: «Пользователи» (authAdminOvl) тайлится 50/50 с «Панель управления» (syncOvl)
     вместо перекрытия — тот же приём, что kdmSqueeze/kdmOpen выше. syncOvl — левая половина,
     authAdminOvl — правая. authAdminOvl.modal несёт инлайн-style max-width/width — перебиваем
     !important, иначе инлайн-стиль сильнее внешнего класса. */
  #syncOvl.syncSqueeze{right:50%;justify-content:center;padding:26px 1.5vw;}
  #syncOvl.syncSqueeze .modal{width:96%;max-width:96%;margin:0;}
  #authAdminOvl.syncOpen{left:50%;justify-content:center;padding:26px 1.5vw;}
  #authAdminOvl.syncOpen .modal{width:96%!important;max-width:96%!important;margin:0;}

  /* ===== Календарь документооборота «📅 Документы» — страница-вид, паттерн #calOvl ===== */
  #docsCalOvl{position:fixed;top:var(--head-h,0px);left:var(--dash-w);right:0;bottom:0;
    background:var(--bg);padding:0;z-index:30;display:none;overflow:hidden;align-items:stretch;}
  #docsCalOvl.show{display:flex;flex-direction:column;}
  body:has(#docsCalOvl.show){overflow:hidden;}
  #docsCalOvl .modal,#docsCalOvl .modal.wide{width:auto;max-width:none;margin:0;border-radius:0;
    box-shadow:none;background:var(--bg);flex:1 1 auto;min-width:0;min-height:0;
    display:flex;flex-direction:column;animation:none;}
  #docsCalOvl .mbody{flex:1 1 auto;min-height:0;display:flex;flex-direction:column;
    padding:10px clamp(12px,1.4vw,22px);overflow:auto;}
  #docsCalOvl .mfoot{flex:0 0 auto;}
  @media(max-width:600px){ #docsCalOvl{left:0;top:calc(var(--head-h,0px) + var(--dash-mob-h,0px));} }

  /* ===== «Задачи ПТО» — экран-РЕЖИМ, как Kenguru/ДКР: не окно (без рамки/тени/×),
     контент просто занимает место главной таблицы (техника — страница-вид #calOvl) ===== */
  #ptoOvl{position:fixed;top:var(--head-h,0px);left:var(--dash-w);right:0;bottom:0;
    background:var(--bg);padding:0;z-index:30;display:none;overflow:hidden;align-items:stretch;}
  #ptoOvl.show{display:flex;flex-direction:column;}
  body:has(#ptoOvl.show){overflow:hidden;}
  #ptoPage{flex:1 1 auto;min-width:0;min-height:0;display:flex;flex-direction:column;
    padding:12px clamp(12px,1.4vw,22px);}
  #ptoTblWrap{flex:1 1 auto;min-height:0;overflow:auto;}
  #ptoFoot{flex:0 0 auto;padding-top:7px;color:var(--muted);font-size:12px;}
  /* Вкладка «Задачи ПТО» НЕ накрывает правую панель «Документы»: правый край экрана
     = её левый край (правило заказчика 2026-08-20 — дашборд слева и «Документы»
     справа остаются видимыми, как на вкладке Kenguru). Значение = ширине #docsMini
     (clamp ниже по файлу) — менять СИНХРОННО. #docsMini есть только в Kenguru
     (kenOnly) и скрыта ≤900px — в этих случаях right:0. Календарь монтажей панель
     по-прежнему накрывает (right:0): его сетке дней нужна вся ширина. */
  @media(min-width:901px){
    body:not(.dir-dkr) #ptoOvl{right:clamp(234px,18.2vw,325px);}
  }
  @media(max-width:600px){ #ptoOvl{left:0;top:calc(var(--head-h,0px) + var(--dash-mob-h,0px));} }
  /* Репорт от 20.08.2026: ПКМ-меню по строке задачи (Открыть/Дублировать/Удалить) —
     стиль зеркалит #pl3dCtxMenu (репорт №447), но position:fixed в body: экран #ptoOvl
     обрезан справа (right под #docsMini), меню у правого края вылезало бы за него.
     z-index 70 — выше экрана (30) и карточки .lvl2 (60): меню открывается только
     с таблицы (карточка закрыта), а любой клик вне закрывает его первым. */
  #ptoCtxMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
    box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:180px;}
  #ptoCtxMenu.show{display:block;}
  #ptoCtxMenu button{display:block;width:100%;text-align:left;padding:7px 10px;border:none;background:none;
    cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
  #ptoCtxMenu button:hover{background:var(--hover);}
  #ptoCtxMenu button.danger{color:#dc2626;}
  /* Репорт №743: ПКМ по шапке главной таблицы → список видимости столбцов (та же
     позиционная модель, что #ptoCtxMenu/#ofCtxMenu — fixed-div в точке клика). */
  #colVisMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
    box-shadow:0 6px 20px rgba(0,0,0,.22);padding:6px;display:none;min-width:210px;max-height:70vh;overflow:auto;}
  #colVisMenu.show{display:block;}
  #colVisMenu .cvmTitle{font-size:11px;font-weight:700;color:var(--muted);text-transform:uppercase;
    letter-spacing:.3px;padding:4px 8px 6px;}
  #colVisMenu label{display:flex;align-items:center;gap:8px;padding:5px 8px;border-radius:6px;cursor:pointer;font-size:13px;color:var(--text);}
  #colVisMenu label:hover{background:var(--hover);}
  #colVisMenu .cvmSep{height:1px;background:var(--line);margin:4px 2px;}
  /* Настройки столбцов остальных таблиц (модуль _ct* в kenguru.js) */
  .ctHid{display:none!important;}
  th.ctEdge{cursor:col-resize!important;}
  th.ctDragging{opacity:.55;}
  th.ctDropL{box-shadow:inset 3px 0 0 #3b82f6;}
  th.ctDropR{box-shadow:inset -3px 0 0 #3b82f6;}
  table.ctFixedTbl td,table.ctFixedTbl th{overflow-wrap:anywhere;}
  #colVisMenu .cvmHint{font-size:11px;line-height:1.35;color:var(--muted);padding:4px 8px;max-width:250px;}
  #colVisMenu .cvmFoot{gap:6px;flex-wrap:wrap;}
  #colVisMenu .cvmFoot{display:flex;justify-content:flex-end;padding:6px 6px 2px;}
  /* Репорт №671 (2026-08-26): ПКМ-меню удаления в «Папке заказа» (#ofCtxMenu, ленивый
     div в body — см. _ofCtxOpen в Учёт_заказов.html) было написано как «точная копия
     #ptoCtxMenu», но CSS-половина копии отсутствовала: без position:fixed/display:none
     меню рендерилось статическим блоком в самом низу body — невидимо и не пряталось,
     заказчик «удаление» не нашёл. z-index 70 > панели #orderFolderPanel (65). */
  #ofCtxMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
    box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:180px;}
  #ofCtxMenu.show{display:block;}
  #ofCtxMenu button{display:block;width:100%;text-align:left;padding:7px 10px;border:none;background:none;
    cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
  #ofCtxMenu button:hover{background:var(--hover);}
  #ofCtxMenu button.danger{color:#dc2626;}
  .docsCalDot{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:3px;vertical-align:middle;}
  .docsCalDot.plan{background:#fde68a;}
  .docsCalDot.closed{background:#bbf7d0;}
  .docsCalDot.transfer{background:#bfdbfe;}
  .docsCalDot.overdue{background:#fca5a5;}
  .docsCalTbl{width:100%;border-collapse:collapse;table-layout:fixed;}
  .docsCalTbl th{background:#f1f3f7;border:1px solid #cbd5e1;padding:6px;font-weight:600;
    text-align:center;font-size:12px;}
  .docsCalTbl td{border:1px solid var(--line2);vertical-align:top;height:76px;padding:4px 6px;
    cursor:pointer;position:relative;}
  .docsCalTbl td.docsCalEmpty{cursor:default;background:var(--row-alt);}
  .docsCalTbl td:hover:not(.docsCalEmpty){background:var(--hover);}
  .docsCalDayNum{font-size:12px;color:var(--muted);}
  .docsCalTbl td.today .docsCalDayNum{color:var(--accent);font-weight:700;}
  .docsCalTbl td.plan{background:#fef9e7;}
  .docsCalTbl td.closed{background:#eefdf3;}
  .docsCalTbl td.transfer{background:#eaf2ff;}
  .docsCalTbl td.overdue{background:#fef2f2;border-color:#dc2626;}
  .docsCalCount{position:absolute;right:6px;bottom:4px;font-size:11px;font-weight:700;
    color:var(--text);background:rgba(0,0,0,.06);border-radius:99px;padding:1px 6px;}
  html.theme-dark .docsCalTbl td.plan{background:#3a3210;}
  html.theme-dark .docsCalTbl td.closed{background:#0f2e1c;}
  html.theme-dark .docsCalTbl td.transfer{background:#1e3a5f;}
  html.theme-dark .docsCalTbl td.overdue{background:#3a1414;}
  html.theme-dark .docsCalCount{background:rgba(255,255,255,.12);}
  #docsCalDayBody{display:flex;flex-direction:column;gap:8px;}
  .docsCalEvRow{display:flex;align-items:center;justify-content:space-between;gap:10px;
    border:1px solid var(--line);border-radius:6px;padding:8px 10px;background:var(--panel);}
  .docsCalEvInfo{font-size:13px;min-width:0;}
  .docsCalEvKind{font-size:11px;color:var(--muted);}
  .docsCalEv-overdue{border-color:#dc2626;}
  .docsCalEv-closed .docsCalEvKind{color:#16a34a;}
  .docsCalEv-transfer .docsCalEvKind{color:#2563eb;}

  #calGrid table{border-collapse:separate;border-spacing:0;font-size:12px;table-layout:fixed;}
  #calGrid thead th{background:#f1f3f7;border:1px solid #cbd5e1;padding:4px 6px;
    font-weight:600;text-align:center;vertical-align:middle;white-space:nowrap;
    position:sticky;z-index:3;}
  /* Шапка из ДВУХ строк: верхняя (monthHead/мета-rowSpan2) — top:0; нижняя
     (числа дней) — top:var(--cal-thead-row1-h) чтобы не наезжала на верхнюю.
     Без двух разных top'ов обе строки прилипали бы к top:0 и числа дней с
     праздничной подсветкой визуально пропадали бы под названиями месяцев. */
  #calGrid thead tr:first-child th{top:0;}
  #calGrid thead tr:nth-child(2) th{top:var(--cal-thead-row1-h,24px);}
  #calGrid thead th.sticky-left{z-index:5;}
  #calGrid thead th.weekend{background:#fee2e2;}
  /* Название месяца — sticky только по top'у (вместе с остальной шапкой). При
     горизонтальной прокрутке ярлык скроллится вместе со «своими» числами дней,
     поэтому шапка-сетка дней и числа всегда выровнены и движутся синхронно. */
  #calGrid thead th.monthHead{position:sticky;top:0;z-index:3;}
  /* Сегодняшний день — заметная синяя подсветка (поверх weekend/holiday, но
     цвета plan/done остаются — это запрошенный приоритет «статус важнее даты»). */
  #calGrid thead th.today{box-shadow:inset 0 -3px 0 var(--accent);color:#1e3a8a;}
  #calGrid tbody td.day.today{box-shadow:inset 0 0 0 2px var(--accent);}
  /* Подсветка ячеек при drag-выделении диапазона. */
  #calGrid tbody td.day.range-sel{background:#dbeafe !important;outline:1px solid var(--accent);}
  #calGrid tbody td{border:1px solid #e5e7eb;padding:3px 5px;vertical-align:middle;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:11px;}
  #calGrid tbody td.meta{background:#fafafa;}
  /* Столбцы «№» и «Вид заявки» — позволяем переносить длинные значения,
     склеенные через «; » при агрегации (например «MP-12/AL; KPRO-007»). */
  #calGrid tbody td.col-num,
  #calGrid thead th.col-num,
  #calGrid tbody td.col-zayavka,
  #calGrid thead th.col-zayavka{
    white-space:normal;word-break:break-word;line-height:1.25;text-align:center;}
  /* Все мета-колонки слева закреплены (sticky-left) — остаются видны при горизонтальной
     прокрутке месяцев. Каждая ячейка получает inline-style left = накопленная ширина
     предыдущих видимых колонок (вычисляется в JS, см. _calMetaCumLeft). При сжатии
     (#calOvl.calSqueeze) скрытые колонки исключаются из накопления. */
  #calGrid thead th.sticky-left,
  #calGrid tbody td.sticky-left{position:sticky;background:#fafafa;}
  #calGrid tbody td.sticky-left{z-index:2;}
  /* Тонкая тень справа — только у ПОСЛЕДНЕЙ закреплённой колонки (визуальная граница
     между закреплённой областью и календарной сеткой). */
  #calGrid thead th.sticky-left.sticky-last,
  #calGrid tbody td.sticky-left.sticky-last{box-shadow:2px 0 0 #94a3b8;}
  /* Ширина дневного столбца — динамическая через --cal-day-w (выставляется в JS
     по calDensity = 15 или 30: чтобы соответствующее число дней помещалось в
     видимую часть #calGrid без горизонтального скролла). Fallback 40px — на
     случай, если JS-расчёт ещё не запускался. */
  #calGrid tbody td.day,
  #calGrid thead th:not(.monthHead):not(.sticky-left){
    min-width:var(--cal-day-w,40px);width:var(--cal-day-w,40px);max-width:var(--cal-day-w,40px);}
  /* Сегментированный переключатель плотности 15/30 дней. */
  #calDensityWrap{display:inline-flex;border:1px solid var(--line);border-radius:6px;
    overflow:hidden;font-size:12px;}
  #calDensityWrap button{background:#fff;border:none;padding:4px 10px;cursor:pointer;
    color:#475569;font-weight:600;}
  #calDensityWrap button+button{border-left:1px solid var(--line);}
  #calDensityWrap button.active{background:var(--accent);color:#fff;}
  #calDensityWrap button:not(.active):hover{background:#eff6ff;color:#1e3a8a;}
  /* scroll-behavior НЕ ставим smooth-ом — иначе drag-to-pan и lazy-load
     при присваивании scrollLeft будут анимироваться рывками. Плавный скролл —
     только явный в calScrollToMonth() через scrollTo({behavior:"smooth"}). */
  #calGrid tbody td.day{text-align:center;vertical-align:middle;cursor:pointer;
    background:#fff;line-height:1.5;font-variant-numeric:tabular-nums;font-size:13px;
    padding:6px 1px;font-weight:500;}
  #calGrid thead th:not(.monthHead):not(.sticky-left){font-size:13px;padding:6px 4px;}
  #calGrid tbody td.day:hover{background:#eff6ff;}
  #calGrid tbody td.day.weekend{background:#fef2f2;}
  /* Праздники — мягкий розовый фон + красная подложка в шапке. */
  #calGrid thead th.holiday{background:#fecaca !important;color:#7f1d1d;font-weight:700;}
  #calGrid tbody td.day.holiday{background:#fee2e2;}
  #calGrid tbody td.day.holiday.weekend{background:#fecaca;}
  /* Мини-тултип над ячейкой с праздником — мгновенно при ховере.
     НЕ задаём position:relative для thead-ячеек: оно перебило бы position:sticky
     из общего правила, и праздничные числа выпадали бы из ряда (визуально съезжали
     вниз). sticky сам по себе является positioning context для абсолютных детей,
     поэтому тултип-псевдоэлемент работает без relative. tbody-ячейки оставляем
     relative — там sticky нет. */
  #calGrid tbody td.day.holiday{position:relative;}
  #calGrid thead th.holiday:hover::after,
  #calGrid tbody td.day.holiday:hover::after{
    content:attr(data-hol);
    position:absolute;left:50%;top:-26px;transform:translateX(-50%);
    background:#7f1d1d;color:#fff;font-size:11px;font-weight:600;
    padding:3px 8px;border-radius:4px;white-space:nowrap;
    box-shadow:0 4px 10px rgba(0,0,0,.25);pointer-events:none;z-index:50;}
  /* Курсор «grab» во время drag-to-scroll по календарной сетке. */
  #calGrid.calPanning{cursor:grabbing !important;user-select:none;}
  #calGrid.calPanning *{cursor:grabbing !important;}
  /* Цвета ячеек по правилу из CLAUDE.md (calendar_color_rules):
       .plan — жёлтый: план отгрузки/монтажа,
       .done — зелёный: выполнено,
       .call — синий: созвон с заказчиком. */
  #calGrid tbody td.day.plan{background:#fde68a;font-weight:700;color:#7c2d12;}
  #calGrid tbody td.day.done{background:#bbf7d0;font-weight:700;color:#14532d;}
  #calGrid tbody td.day.call{background:#bfdbfe;font-weight:700;color:#1e3a8a;}
  /* план + выполнено в одной ячейке (факт совпал с планом): жёлто-зелёная диагональ —
     план остаётся виден, ✓ показывает выполнение. */
  #calGrid tbody td.day.plandone{
    background:linear-gradient(135deg,#fde68a 0%,#fde68a 46%,#bbf7d0 54%,#bbf7d0 100%);
    font-weight:700;color:#14532d;}
  #calGrid tbody tr.row-otg{background:#fff;}
  #calGrid tbody tr.row-mnt{background:#f8fafc;}
  #calGrid tbody tr.row-none{background:#fef9c3;}  /* заказ без даты в текущем месяце */
  #calGrid tbody tr.row-none td.row-type{color:#7c2d12;}
  /* note-cell: НЕ задаём position:relative — иначе перебьёт position:sticky из
     .sticky-left (специфичность та же, note-cell объявлен ниже, выиграл бы он, и
     колонка примечания перестала бы закрепляться). Sticky тоже создаёт
     containing block для абсолютных детей, так что .note-edit-btn по-прежнему
     анкорится к ячейке. */
  #calGrid tbody td.note-cell{font-size:10px;color:#475569;line-height:1.3;
    white-space:pre-wrap;padding-right:24px;vertical-align:top;}
  #calGrid tbody td.note-cell .note-text{display:block;max-height:48px;
    overflow:hidden;text-overflow:ellipsis;}
  #calGrid tbody td.note-cell .note-edit-btn{
    display:inline-flex;align-items:center;justify-content:center;
    position:absolute;top:3px;right:3px;
    width:18px;height:18px;padding:0;
    background:#fff;border:1px solid #94a3b8;border-radius:3px;
    font-size:12px;line-height:1;cursor:pointer;color:#1e3a8a;
    transition:background .12s,border-color .12s;}
  #calGrid tbody td.note-cell .note-edit-btn:hover{
    background:#dbeafe;border-color:var(--accent);color:#1e3a8a;}
  #calGrid tbody td.note-cell .note-edit-ta{
    width:100%;box-sizing:border-box;font-family:inherit;font-size:11px;
    padding:4px 6px;border:1px solid #3b82f6;border-radius:4px;
    resize:vertical;min-height:48px;}
  /* Шапка двухуровневая: верхняя строка — название месяца (colspan по дням),
     нижняя — числа 1..N. */
  #calGrid thead th.monthHead{background:#e2e8f0;font-size:12px;border-bottom:2px solid #94a3b8;}
  #calGrid thead th.monthHead.alt{background:#f1f5f9;}
  /* Drag-handle строки заказчика. */
  #calGrid tbody td.dragHandle{width:18px;cursor:grab;text-align:center;color:#94a3b8;
    user-select:none;background:#fafafa;font-size:14px;}
  #calGrid tbody td.dragHandle:hover{color:var(--accent);background:#eff6ff;}
  #calGrid tbody tr.calDropTarget td{border-top:2px solid var(--accent);}
  #calGrid tbody tr.calDragging{opacity:.4;}
  /* Множественный выбор строк календаря (массовый перенос, аналог списка комплексов).
     Тонируем sticky-left мета-ячейки — они всегда видны в левой части при прокрутке. */
  #calGrid tbody tr.calSelRow td.meta,
  #calGrid tbody tr.calSelRow td.sticky-left,
  #calGrid tbody tr.calSelRow td.dragHandle{background:#dbe9ff !important;}
  #calGrid tbody tr.calSelRow td.dragHandle{box-shadow:inset 3px 0 0 var(--accent);color:var(--accent);}
  html.theme-dark #calGrid tbody tr.calSelRow td.meta,
  html.theme-dark #calGrid tbody tr.calSelRow td.sticky-left,
  html.theme-dark #calGrid tbody tr.calSelRow td.dragHandle{background:#1e3a5f !important;}
  /* Подсказка выбора строк над сеткой календаря. */
  #calSelHint{align-items:center;}
  #calSelHint a:hover{color:var(--accent-d);}
  /* Поп-ап для проставления плана/выполнения/созвона по клику на ячейку дня. */
  #calCellPopup{position:fixed;z-index:200;background:#fff;border:1px solid var(--line);
    border-radius:8px;padding:10px;box-shadow:0 8px 28px rgba(0,0,0,.2);
    min-width:240px;max-width:380px;font-size:12px;display:flex;
    flex-direction:column;gap:6px;}
  #calCellPopup .hdr{font-weight:700;font-size:12px;color:#0f172a;padding-bottom:4px;
    border-bottom:1px solid var(--line);margin-bottom:4px;}
  #calCellPopup .ordSel{font-size:11px;padding:5px 7px;border:1px solid var(--line);
    border-radius:5px;margin-bottom:4px;}
  #calCellPopup button{text-align:left;border:1px solid var(--line);background:#fff;
    border-radius:5px;padding:6px 8px;cursor:pointer;font-size:12px;}
  #calCellPopup button:hover{background:#f1f5f9;}
  #calCellPopup button.plan{background:#fde68a;color:#7c2d12;border-color:#fcd34d;}
  #calCellPopup button.done{background:#bbf7d0;color:#14532d;border-color:#86efac;}
  #calCellPopup button.call{background:#bfdbfe;color:#1e3a8a;border-color:#93c5fd;}
  #calCellPopup button.clear{background:#fee2e2;color:#7f1d1d;border-color:#fca5a5;}
  #calCellPopup .close{position:absolute;top:4px;right:6px;background:none;border:none;
    cursor:pointer;color:#94a3b8;font-size:16px;}
  /* Сетка для кнопок Часть 1 / Часть 2 — два столбца с одинаковой шириной.
     Кнопки внутри grid'а должны быть text-align:center, чтобы метки красиво
     центрировались (по умолчанию popup-кнопки — text-align:left). */
  #calCellPopup .partGrid{display:grid;grid-template-columns:1fr 1fr;gap:4px;}
  #calCellPopup .partGrid button{text-align:center;padding:6px 6px;}
  #calCellPopup .partGrid+.partGrid{margin-top:2px;}
  #calCellPopup .rangeRow{display:flex;align-items:center;gap:6px;padding:4px 6px;
    background:#f8fafc;border:1px solid var(--line);border-radius:5px;margin-bottom:2px;
    transition:background 150ms,border-color 150ms;}
  #calCellPopup .rangeRow.active{background:#dbeafe;border-color:#3b82f6;}
  #calCellPopup .rangeLbl{font-size:11px;color:var(--muted);white-space:nowrap;}
  #calCellPopup .rangeRow.active .rangeLbl{color:#1e3a8a;font-weight:600;}
  #calCellPopup .rangeInp{flex:1;font-size:12px;padding:3px 5px;
    border:1px solid var(--line);border-radius:4px;}
  /* Многодневные отметки в календаре: тонкий пунктир по верхней границе показывает,
     что ячейка — продолжение диапазона. */
  #calGrid tbody td.day.range{border-top:1px dashed #94a3b8 !important;
    border-bottom:1px dashed #94a3b8 !important;}
  #calGrid tbody td.day.range.range-start{border-left:1px solid #94a3b8 !important;
    border-top-left-radius:3px;border-bottom-left-radius:3px;}
  #calGrid tbody td.day.range.range-end{border-right:1px solid #94a3b8 !important;
    border-top-right-radius:3px;border-bottom-right-radius:3px;}
  /* Подсветка всей строки при наведении — включая закреплённые мета-ячейки слева
     (№, Заказчик, …). Чтобы перебить background:#fafafa у sticky-left, используем
     !important. */
  #calGrid tbody tr:hover td{background:#eef2ff !important;}
  #calGrid tbody tr.row-otg td.meta.row-type{color:var(--accent-d);font-weight:700;}
  #calGrid tbody tr.row-mnt td.meta.row-type{color:#a16207;font-weight:700;}
  .modal.narrow{width:clamp(300px,92vw,560px);}
  /* Репорт bugmscx2yf0kdo1: шапка карточки должна ужиматься/переноситься при узком
     окне (боковая панель «Скриншоты» отъедает ширину) — разрешаем перенос строк
     и сжатие заголовка на любой ширине, не только на телефоне. */
  .modal h2{font-size:clamp(14px,0.3vw+12.5px,18px);padding:14px clamp(12px,1.4vw,22px);border-bottom:1px solid var(--line);display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
  .modal h2 #mTitle{min-width:0;overflow-wrap:anywhere;}
  .modal h2 .x{margin-left:auto;border:none;background:none;font-size:20px;color:var(--muted);line-height:1;}
  .modal h2 .copyHdr{border:1px solid var(--line);background:#fff;color:var(--muted);font-size:11px;font-weight:600;line-height:1;cursor:pointer;border-radius:6px;padding:4px 8px;white-space:nowrap;}
  .modal h2 .copyHdr:hover{color:var(--accent);border-color:var(--accent);}
  .modal h2 .copyHdr:active{transform:translateY(1px);}
  /* Репорт №740: кнопка «Журнал» в окне репорта об ошибке была неотличима от служебной
     .copyHdr («Копировать») — заметнее: акцентная рамка/фон, иконка, крупнее шрифт. */
  .modal h2 .bugJrnHdrBtn{border:1px solid var(--accent);background:rgba(37,99,235,.08);color:var(--accent);
    font-size:12.5px;font-weight:700;line-height:1;cursor:pointer;border-radius:7px;padding:6px 11px;white-space:nowrap;}
  .modal h2 .bugJrnHdrBtn:hover{background:var(--accent);color:#fff;}
  .modal h2 .bugJrnHdrBtn:active{transform:translateY(1px);}
  html.theme-dark .modal h2 .bugJrnHdrBtn{background:rgba(96,165,250,.14);}
  .mbody{padding:16px clamp(12px,1.4vw,22px);font-size:var(--fs-base);}
  .grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
  /* В шапке карточки слева — основные поля + цвет/менеджер,
     справа — секция «Услуги, документация, дополнительно» (renderReqSection)
     с вертикально стэканными карточками. */
  .cardTop{display:grid;grid-template-columns:1fr minmax(0,320px);gap:14px;align-items:start;}
  .cardRight{display:flex;flex-direction:column;gap:12px;}
  .cardRight .sect{margin-top:0;}
  /* Репорт №227: узкая карточка рядом с широкой панелью сравнения — cardRight
     прячется целиком, вместо него компактная подсказка (_cardRightApplySqueeze). */
  .cardRight.crSqueeze>.sect{display:none;}
  .cardRightHint{display:none;align-items:center;justify-content:center;text-align:center;
    min-height:60px;padding:12px;border:1px dashed var(--line);border-radius:8px;
    color:var(--muted);font-size:12.5px;line-height:1.4;}
  .cardRight.crSqueeze .cardRightHint{display:flex;}
  .cardPair{display:grid;grid-template-columns:1fr 3fr;gap:12px;margin-top:16px;align-items:stretch;}
  .cardPair>.sect{margin-top:0;}
  /* Три равнозначных поля в ряд (напр. Длина/Ширина/Высота детали). */
  .cardTriple{display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;margin-top:16px;align-items:stretch;}
  /* Услуги внутри cardTop — построчно (одна колонка), карточки идут друг под другом. */
  #sectReq .reqGrid{display:flex;flex-direction:column;gap:10px;margin-top:6px;}
  #sectReq .reqCol{border:1px solid var(--line);border-radius:8px;padding:8px 10px;background:#fff;
    display:flex;flex-direction:column;gap:6px;min-width:0;}
  #sectReq .reqCol .substep{margin-left:0!important;}
  .fld{display:flex;flex-direction:column;gap:3px;}
  .fld.full{grid-column:1/3;}
  .fld label{font-size:11px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.3px;}
  .fld input,.fld select,.fld textarea{border:1px solid var(--line);border-radius:6px;padding:7px 9px;font-size:13px;font-family:inherit;}
  .fld textarea{resize:vertical;min-height:50px;}
  /* Авторастущие однострочные поля карточки (репорт bugmscxm7u8ne7i): выглядят как
     обычный input, высоту подгоняет _taAutoGrow по содержимому. */
  .fld textarea.fldGrow{resize:none;min-height:0;overflow:hidden;line-height:1.35;}
  .sect{margin-top:16px;border:1px solid var(--line);border-radius:8px;padding:12px;background:var(--bg);}
  .sect .ttl{font-size:11px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.4px;margin-bottom:10px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
  /* ДКР: компактнее — меньше отступы между блоками карточки заказа */
  .dkrCard .sect{margin-top:10px;padding:10px;}
  .dkrCard .sect .ttl{margin-bottom:6px;}
  .dkrCard .cardTop{gap:10px;}
  .dkrCard .cardPair{margin-top:10px;}
  .reqrow{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:6px 8px;background:#fff;border:1px solid var(--line);border-radius:6px;margin-bottom:6px;}
  .reqrow .rname{flex:1;min-width:130px;font-weight:600;}
  .reqrow label{display:flex;align-items:center;gap:5px;font-size:12px;cursor:pointer;color:var(--muted);}
  .reqrow input{width:15px;height:15px;cursor:pointer;}
  .reqrow.off .rname{color:#9aa1ad;font-weight:400;}
  .substep{margin:-2px 0 8px 34px;padding:6px 10px;background:#fff;border:1px solid var(--line);
    border-left:3px solid var(--accent);border-radius:0 6px 6px 0;font-size:12.5px;color:#475569;}
  .substep.off{opacity:.5;}
  .cxtbl{width:100%;border-collapse:collapse;font-size:12px;background:#fff;}
  .cxtbl th{background:#f1f3f7;border:1px solid var(--line);padding:5px 7px;text-align:left;font-weight:600;}
  .cxtbl td{border:1px solid var(--line2);padding:4px 7px;}
  .cxtbl input{width:56px;border:1px solid var(--line);border-radius:4px;padding:3px 5px;font-size:12px;}
  /* Кнопки-действия в строке (✎ примечание, × удалить, ≡ перетащить) — видны ВСЕГДА,
     без мерцания и привязки к hover. Без opacity/visibility-переходов. */
  .cxtbl .del{border:none;background:none;color:#dc2626;font-size:15px;
    cursor:pointer;padding:0;}
  .cxtbl .cxNoteBtn{border:none;background:none;color:#64748b;font-size:13px;
    cursor:pointer;padding:0 4px;}
  /* Кнопка с примечанием — выделена синим как индикатор записи. */
  .cxtbl .cxNoteBtn.hasNote{color:var(--accent);}
  .cxGrip{display:inline-block;cursor:grab;color:#94a3b8;font-size:15px;line-height:1;
    user-select:none;padding:0 4px;}
  .cxGrip:active{cursor:grabbing;}
  /* Подсветка строки при наведении — для удобства идентификации активной строки. */
  .cxtbl tbody tr:hover td{background:#f8fafc;}
  .qtyWrap{display:inline-flex;align-items:center;border:1px solid var(--line);border-radius:4px;overflow:hidden;}
  .qtyWrap button{border:none;background:#f1f5f9;width:22px;height:24px;cursor:pointer;font-size:13px;
    color:#0f172a;line-height:1;padding:0;}
  .qtyWrap button:hover{background:#e2e8f0;}
  .qtyWrap input{border:none;width:44px;text-align:center;font-size:12px;padding:3px 0;outline:none;}
  /* Переключатель «Готово» по позиции (доставка/монтаж) — размер как кнопки +/- в «Кол-во», цвета приглушённые. */
  .cxDoneBtn{width:26px;height:24px;border:1px solid var(--line);border-radius:4px;background:#f1f5f9;
    color:#94a3b8;font-size:14px;line-height:1;padding:0;cursor:pointer;}
  .cxDoneBtn:hover{background:#e2e8f0;}
  .cxDoneBtn.on{background:#e8f1ea;border-color:#bcd7c4;color:#4a8c63;}
  .cxDoneBtn.on:hover{background:#dcebe0;}
  details.cxExtras{margin-top:10px;}
  details.cxExtras > summary{cursor:pointer;font-size:11px;color:#64748b;list-style:none;
    padding:6px 0;user-select:none;}
  details.cxExtras > summary::-webkit-details-marker{display:none;}
  details.cxExtras > summary::before{content:"▸ ";color:#94a3b8;}
  details.cxExtras[open] > summary::before{content:"▾ ";}
  details.cxExtras .row{margin-top:6px;}
  .cxQuickInput{display:flex;gap:6px;align-items:stretch;margin-top:10px;}
  .cxQuickInput input{flex:1;font-size:12px;border:1px solid var(--line);border-radius:4px;padding:5px 8px;}
  .cxtbl tbody tr.dragover td{border-top:2px solid var(--accent);}
  .cxtbl tbody tr.dragready{cursor:grabbing;}
  .cxtbl tbody tr.dragready td{background:#fff7ed;box-shadow:inset 0 0 0 2px var(--accent);}
  /* Порядковый номер позиции комплекса. */
  .cxtbl .cxNumCell{text-align:center;color:#64748b;font-size:11px;font-variant-numeric:tabular-nums;}
  /* Строка, выбранная для множественного перемещения (Ctrl/Shift+клик по ручке). */
  .cxtbl tbody tr.cxSelRow > td{background:#dbeafe !important;}
  .cxtbl .cxNoteCell{font-size:11px;color:#475569;font-style:italic;padding:2px 7px 4px;
    background:#f8fafc;border-top:1px dashed var(--line2);}
  /* Кликабельные строки: справочник комплексов и список комплексов заказа */
  #cxRefBody tr{cursor:pointer;}
  #cxRefBody tr:hover td{background:#eff6ff;}
  .cxtbl tbody tr.cxRowClickable{cursor:pointer;}
  .cxtbl tbody tr.cxRowClickable:hover > td:not(.cxNoteCell){background:#eff6ff;}
  .cxNotePop{position:absolute;z-index:1500;background:#fff;border:1px solid var(--line);
    border-radius:8px;padding:10px;box-shadow:0 8px 24px rgba(0,0,0,.18);min-width:260px;}
  .cxNotePop .swatches{display:flex;gap:5px;flex-wrap:wrap;margin-bottom:8px;}
  .cxNotePop .sw{width:22px;height:22px;border-radius:4px;cursor:pointer;
    border:2px solid transparent;}
  .cxNotePop .sw.none{background:repeating-linear-gradient(45deg,#fff,#fff 4px,#e5e7eb 4px,#e5e7eb 6px);}
  .cxNotePop .sw.sel{border-color:#0f172a;}
  .cxNotePop textarea{width:100%;min-height:72px;font-size:12px;font-family:inherit;
    border:1px solid var(--line);border-radius:4px;padding:5px 6px;resize:vertical;box-sizing:border-box;}
  .cxNotePop .row{display:flex;justify-content:flex-end;gap:6px;margin-top:8px;}
  .cxempty{color:var(--muted);padding:8px 2px;font-size:12px;}
  .mfoot{padding:12px 18px;border-top:1px solid var(--line);display:flex;gap:8px;align-items:center;flex-wrap:wrap;}
  .btn.danger{color:#dc2626;border-color:#f0c0c0;}
  .btn.danger:hover{background:#fdecec;}
  .catbar{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;}
  .catbar input,.catbar select{border:1px solid var(--line);border-radius:6px;padding:6px 8px;font-size:12px;}
  .catbar input{flex:1;min-width:150px;}
  .catlist{max-height:48vh;overflow:auto;border:1px solid var(--line);border-radius:6px;}
  .catlist table{font-size:12px;}
  .catlist th{position:sticky;top:0;}
  .catlist tr{cursor:pointer;}
  .catlist tr:hover td{background:var(--hover);}
  /* Кнопки переключения вида KENGURU / KPRO в справочнике */
  .cxRefKindBtn{font-weight:600;}
  .cxRefKindBtn.active{background:var(--accent);color:#fff;border-color:var(--accent);}
  .cxRefKindBtn.active:hover{background:var(--accent-d);}
  /* Шапки группировки (Excel-style) и подгруппировки в справочнике */
  #cxRefBody tr.grpRow,#cxSpecBody tr.grpRow,#catBody tr.grpRow,#mkJournalBody tr.grpRow{cursor:pointer;background:var(--panel);}
  #cxRefBody tr.grpRow:hover td,#cxSpecBody tr.grpRow:hover td,#catBody tr.grpRow:hover td,#mkJournalBody tr.grpRow:hover td{background:var(--hover);}
  #cxRefBody tr.grpRow td,#cxSpecBody tr.grpRow td,#catBody tr.grpRow td,#mkJournalBody tr.grpRow td{font-weight:700;color:var(--accent-d);padding:7px 8px;border-top:2px solid var(--accent);border-bottom:1px solid var(--line);}
  #cxRefBody tr.subRow,#catBody tr.subRow,#mkJournalBody tr.subRow{cursor:pointer;background:var(--panel);}
  #catBody tr[role="button"]:focus-visible{outline:3px solid var(--accent);outline-offset:-3px;}
  #cxRefBody tr.subRow:hover td,#catBody tr.subRow:hover td,#mkJournalBody tr.subRow:hover td{background:var(--hover);}
  #cxRefBody tr.subRow td,#catBody tr.subRow td,#mkJournalBody tr.subRow td{font-weight:600;color:var(--text);padding:5px 8px 5px 26px;border-top:1px solid var(--accent-d);border-bottom:1px solid var(--line);}
  #cxRefBody tr.grpRow .grpToggle,#cxRefBody tr.subRow .grpToggle,#cxSpecBody tr.grpRow .grpToggle,#catBody tr.grpRow .grpToggle,#catBody tr.subRow .grpToggle,#mkJournalBody tr.grpRow .grpToggle,#mkJournalBody tr.subRow .grpToggle{
    display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;
    margin-right:6px;color:var(--accent-d);user-select:none;}

  /* журнал замечаний: верхний уровень — разделы по типу документа (схема / чертёж / паспорт) */
  #mkJournalBody tr.kindRow{cursor:pointer;background:#3730a3;}
  #mkJournalBody tr.kindRow:hover td{background:#4338ca;}
  #mkJournalBody tr.kindRow td{font-weight:800;color:#fff;padding:9px 8px;border-top:2px solid #1e1b4b;border-bottom:1px solid #1e1b4b;letter-spacing:.02em;}
  #mkJournalBody tr.kindRow .grpToggle{display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;margin-right:6px;color:#fff;user-select:none;}
  /* под разделом типа — номенклатурные группы/подгруппы с доп. отступом */
  #mkJournalBody tr.grpRow td{padding-left:18px;}
  #mkJournalBody tr.subRow td{padding-left:36px;}
  /* «Структура как в номенклатуре» для доп. таблиц со списком комплексов (Паспорта, Сводка) */
  #paspListBody tr.grpRow,#cxSumOvl .sumTbl tr.grpRow{cursor:pointer;background:var(--panel);}
  #paspListBody tr.grpRow:hover td,#cxSumOvl .sumTbl tr.grpRow:hover td{background:var(--hover);}
  #paspListBody tr.grpRow td,#cxSumOvl .sumTbl tr.grpRow td{font-weight:700;color:var(--accent-d);padding:7px 8px;border-top:2px solid var(--accent);border-bottom:1px solid var(--line);}
  #paspListBody tr.subRow,#cxSumOvl .sumTbl tr.subRow{cursor:pointer;background:var(--panel);}
  #paspListBody tr.subRow:hover td,#cxSumOvl .sumTbl tr.subRow:hover td{background:var(--hover);}
  #paspListBody tr.subRow td,#cxSumOvl .sumTbl tr.subRow td{font-weight:600;color:var(--text);padding:5px 8px 5px 26px;border-top:1px solid var(--accent-d);border-bottom:1px solid var(--line);}
  #paspListBody tr.grpRow .grpToggle,#paspListBody tr.subRow .grpToggle,#cxSumOvl .sumTbl tr.grpRow .grpToggle,#cxSumOvl .sumTbl tr.subRow .grpToggle{display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;margin-right:6px;color:var(--accent-d);user-select:none;}
  /* группировка пане «Спецификация заказа → По комплексам» (блоки, заголовки-div) */
  #ospPaneByComplex .ospGrpRow{cursor:pointer;background:var(--panel);color:var(--accent-d);font-weight:700;padding:7px 10px;border:1px solid var(--line);border-left:3px solid var(--accent);border-radius:6px;margin:10px 0 4px;}
  #ospPaneByComplex .ospGrpRow:hover{background:var(--hover);}
  #ospPaneByComplex .ospSubRow{cursor:pointer;background:var(--panel);color:var(--text);font-weight:600;padding:5px 10px 5px 22px;border:1px solid var(--line);border-left:3px solid var(--accent-d);border-radius:6px;margin:4px 0 4px 12px;}
  #ospPaneByComplex .ospSubRow:hover{background:var(--hover);}
  #ospPaneByComplex .ospGrpRow .grpToggle,#ospPaneByComplex .ospSubRow .grpToggle{display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;margin-right:6px;color:var(--accent-d);user-select:none;}
  #ospPaneByComplex .ospGrpCnt{font-weight:400;color:var(--muted);font-size:11px;}
  /* Репорт bugms4w6vfvl5za: комплекс в пане — сворачиваемый заголовок (3-й уровень) */
  #orderSpecPanel .ospBlk h4{cursor:pointer;user-select:none;}
  #orderSpecPanel .ospBlk h4 .grpToggle{display:inline-block;width:14px;text-align:center;font-family:monospace;font-weight:900;margin-right:4px;color:var(--accent-d);user-select:none;}
  /* Репорт bugms4vxylv5jlf: итог «Общий вес комплекса» в окне спецификации —
     светлая заливка через класс (тёмная тема переопределяет в своём блоке) */
  .specTotRow{background:#f1f5f9;font-weight:700;}
  /* №304: клик по «≈X м³ (по N из M деталей)» показывает недостающие детали */
  #cxSpecTotalVol.cxSpecClickable{cursor:pointer;text-decoration:underline dotted;}
  #cxSpecBody tr.cxSpecRowMissing{background:#fef3c7 !important;transition:background 1.8s ease;}
  html.theme-dark #cxSpecBody tr.cxSpecRowMissing{background:#4a3a10 !important;}
  /* (тёмные заливки осп-групп убраны — базовый «рамочный» стиль адаптивен через var) */
  html.theme-dark #mkJournalBody tr.kindRow{background:#312e81;}
  html.theme-dark #mkJournalBody tr.kindRow:hover td{background:#3730a3;}

  .mat{display:inline-block;width:24px;text-align:center;border-radius:4px;font-size:10px;font-weight:700;color:#fff;}
  .mat.AL{background:#0891b2;} .mat.ST{background:#7c3aed;} .mat.N{background:#475569;}
  /* sync */
  .syncState{border:1px solid var(--line);border-radius:8px;padding:11px 13px;background:var(--bg);margin-bottom:14px;font-size:13px;}
  .syncState b{font-size:13px;}
  .syncStep{margin-bottom:14px;}
  .syncStep h3{font-size:12px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);margin-bottom:7px;}
  .syncStep p{color:var(--muted);font-size:12px;margin-bottom:8px;line-height:1.5;}
  .syncBtns{display:flex;gap:8px;flex-wrap:wrap;}
  .lsBar{height:15px;background:#eef1f5;border:1px solid var(--line);border-radius:8px;overflow:hidden;}
  .lsFill{height:100%;width:0;background:#16a34a;transition:width .3s;}
  .lsFill.warn{background:#d97706;}
  .lsFill.crit{background:#dc2626;}
  /* вкладки внутри модалок */
  .tabBar{display:flex;gap:2px;border-bottom:2px solid var(--line);margin-bottom:10px;}
  .tabBar .tab{padding:8px 14px;cursor:pointer;border:1px solid var(--line);border-bottom:none;
    background:#f8fafc;border-radius:6px 6px 0 0;font-size:12px;font-weight:600;color:#475569;margin-bottom:-2px;}
  .tabBar .tab:hover{background:#f1f5f9;}
  .tabBar .tab.active{background:#fff;color:var(--accent);border-bottom:2px solid #fff;}
  .tabPane{display:none;}
  .tabPane.show{display:block;}
  /* строка детали без веса */
  #cxRefPartsBody tr.noweight{background:#fef3c7;}
  #cxRefPartsBody tr.noweight:hover{background:#fde68a;}
  #cxRefPartsBody tr.noweight td{border-color:#f59e0b;}
  /* сортируемые заголовки */
  .sortable{cursor:pointer;user-select:none;}
  .sortable:hover{background:#e2e8f0;}
  .sortable .arr{color:#94a3b8;font-size:10px;margin-left:2px;}
  .sortable.asc .arr,.sortable.desc .arr{color:var(--accent);}
  #cxSumOvl .sumTbl{width:100%;border-collapse:collapse;font-size:12px;margin-top:6px;}
  #cxSumOvl .sumTbl thead th{position:sticky;top:0;z-index:3;}
  #cxSumOvl .sumTbl th{background:#f1f3f7;border:1px solid var(--line);padding:5px 7px;text-align:left;font-weight:600;
    cursor:pointer;user-select:none;white-space:nowrap;}
  #cxSumOvl .sumTbl th.r{text-align:right;}
  #cxSumOvl .sumTbl th:hover{background:#e2e8f0;}
  #cxSumOvl .sumTbl th .arr{color:#94a3b8;font-size:10px;margin-left:2px;}
  #cxSumOvl .sumTbl th.sort .arr{color:var(--accent);}
  #cxSumOvl .sumTbl td{border:1px solid var(--line2);padding:4px 7px;}
  #cxSumOvl .sumTbl td.r{text-align:right;font-variant-numeric:tabular-nums;}
  #cxSumOvl .sumTbl tbody tr:hover td{background:#f8fafc;cursor:pointer;}
  #cxSumOvl .sumTbl tbody tr.tot:hover td{background:#f1f5f9;cursor:default;}
  #cxOrdPop{position:absolute;z-index:1600;background:#fff;border:1px solid var(--line);
    border-radius:8px;box-shadow:0 8px 28px rgba(0,0,0,.18);padding:10px;min-width:300px;max-width:520px;
    max-height:380px;overflow:auto;}
  #cxOrdPop .ph{font-size:12px;font-weight:600;margin-bottom:6px;color:#0f172a;}
  #cxOrdPop .ph .sub{color:#64748b;font-weight:400;margin-left:6px;}
  #cxOrdPop table{width:100%;border-collapse:collapse;font-size:12px;}
  #cxOrdPop th{background:#f1f3f7;padding:4px 6px;border:1px solid var(--line);text-align:left;font-weight:600;}
  #cxOrdPop td{padding:4px 6px;border:1px solid var(--line2);}
  #cxOrdPop tr{cursor:pointer;}
  #cxOrdPop tr:hover td{background:#eff6ff;}
  #cxOrdPop .r{text-align:right;font-variant-numeric:tabular-nums;}
  #cxOrdPop .close{float:right;border:none;background:none;font-size:16px;color:#64748b;cursor:pointer;line-height:1;}
  #cxSumOvl .sumTotal{font-size:14px;font-weight:700;margin:8px 0;display:flex;gap:18px;flex-wrap:wrap;}
  #cxSumOvl .sumTotal .v{color:var(--accent);}
  #cxSumOvl .sumFilter{display:flex;gap:8px;align-items:center;margin:10px 0 4px;flex-wrap:wrap;}
  #cxSumOvl .sumFilter input{flex:1;min-width:180px;padding:6px 10px;font-size:12px;
    border:1px solid var(--line);border-radius:6px;}
  #cxSumOvl .sumFilter .lbl{font-size:11px;color:#64748b;}
  #cxSumOvl details{margin-top:14px;}
  #cxSumOvl summary{cursor:pointer;font-weight:600;padding:6px 0;font-size:13px;}
  #cxSumOvl .twoCol{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
  @media(max-width:720px){#cxSumOvl .twoCol{grid-template-columns:1fr;}}
  @keyframes rowFlash{0%{background:#fff7ed;}100%{background:transparent;}}
  tr.rowHighlight td{animation:rowFlash 1.2s ease-out;}

  /* Таблица «Было / Стало» в окне подробностей истории. */
  #histDiffOvl .diffTbl{width:100%;border-collapse:collapse;font-size:12px;}
  #histDiffOvl .diffTbl th{background:#f1f3f7;border:1px solid var(--line);padding:6px 8px;text-align:left;font-weight:600;}
  #histDiffOvl .diffTbl td{border:1px solid var(--line2);padding:6px 8px;vertical-align:top;}
  #histDiffOvl .diffTbl td.before{background:#fef2f2;color:#7f1d1d;}
  #histDiffOvl .diffTbl td.after{background:#f0fdf4;color:#166534;}
  #histDiffOvl .diffTbl td.before pre,#histDiffOvl .diffTbl td.after pre{margin:0;font-family:inherit;white-space:pre-wrap;word-break:break-word;}
  #histDiffOvl .diffTbl td .empty{color:#94a3b8;font-style:italic;}
  /* Строки в таблице истории — кликабельные. */
  #histBody tr,#ovl .modal .sect table.cxtbl tbody tr[data-hist]{cursor:pointer;}
  #histBody tr:hover td{background:#eff6ff;}

  /* === Анимации карточки заказа === */
  /* Выдвигающийся список — подпункты услуг (substep) и условные блоки
     раскрываются как аккордеон: max-height с 0 до 600px + scaleY от точки сверху. */
  @keyframes accordionDown{
    0%  {opacity:0; max-height:0;   transform:scaleY(.92) translateY(-6px);}
    60% {opacity:1;}
    100%{opacity:1; max-height:600px; transform:scaleY(1) translateY(0);}
  }
  #sectReq .substep{overflow:hidden;transform-origin:top center;}
  /* Анимация играет ТОЛЬКО когда у substep есть класс .animate — выставляется
     при первом открытии карточки или при включении услуги.
     При кликах по подпунктам анимация не воспроизводится. */
  #sectReq .substep.animate{animation:accordionDown .35s cubic-bezier(.2,.7,.3,1) both;}
  #sectReq .reqCol > .substep.animate > *{animation:accordionDown .3s cubic-bezier(.2,.7,.3,1) both;
    transform-origin:top center;}
  #sectReq .reqCol > .substep.animate > *:nth-child(1){animation-delay:.00s;}
  #sectReq .reqCol > .substep.animate > *:nth-child(2){animation-delay:.04s;}
  #sectReq .reqCol > .substep.animate > *:nth-child(3){animation-delay:.08s;}
  #sectReq .reqCol > .substep.animate > *:nth-child(4){animation-delay:.12s;}
  #sectReq .reqCol > .substep.animate > *:nth-child(5){animation-delay:.16s;}
  /* Активная карточка услуги — лёгкая подсветка границы + фон. */
  #sectReq .reqCol{transition:border-color .25s ease,background .25s ease,box-shadow .25s ease;}
  #sectReq .reqCol:not(.off){border-color:#93c5fd;background:#f0f9ff;
    box-shadow:0 1px 3px rgba(26,115,232,.06);}
  #sectReq .reqCol.off{opacity:.78;}
  /* Бейдж статуса — мягкое появление при ререндере. */
  @keyframes badgePulse{0%{transform:scale(1);}50%{transform:scale(1.06);}100%{transform:scale(1);}}
  #sectReq .badge{display:inline-block;animation:badgePulse .35s ease-out;}
  /* Кнопки внутри карточки — лёгкий подъём при наведении. */
  #ovl .modal .btn:not(:disabled){transition:transform .15s ease,box-shadow .15s ease,
    background .15s ease,border-color .15s ease;}
  #ovl .modal .btn:not(:disabled):hover{transform:translateY(-1px);
    box-shadow:0 3px 8px rgba(0,0,0,.10);}
  #ovl .modal .btn:not(:disabled):active{transform:translateY(0);box-shadow:0 1px 2px rgba(0,0,0,.06);}
  /* Поля ввода — focus-glow. */
  #ovl .modal input:not([type=checkbox]):not([type=radio]),
  #ovl .modal textarea,
  #ovl .modal select{transition:border-color .18s ease,box-shadow .18s ease;}
  #ovl .modal input:not([type=checkbox]):not([type=radio]):focus,
  #ovl .modal textarea:focus,
  #ovl .modal select:focus{outline:none;border-color:var(--accent);
    box-shadow:0 0 0 3px rgba(26,115,232,.15);}
  /* Цветовые свотчи цвета заказа (поповер #mColorPop) — масштаб при наведении/выборе. */
  .hdrColorPop .swatch{transition:transform .15s ease,box-shadow .15s ease,outline-color .15s ease;}
  .hdrColorPop .swatch:hover{transform:scale(1.12);}
  .hdrColorPop .swatch.sel{transform:scale(1.15);box-shadow:0 0 0 2px var(--accent);}
  /* Строки таблиц комплексов/контактов — мягкая подсветка при наведении. */
  #ovl .modal table.cxtbl tbody tr{transition:background .15s ease;}
  /* Чекбокс «требуется» вместе с названием — лёгкое выделение при on. */
  #sectReq .reqCol:not(.off) > .reqrow > label{color:#0f172a;}
  #sectReq .reqCol.off > .reqrow > label{color:#64748b;}
  /* Анимация смены значка раскрытия для групп каталога/справочника. */
  .grpToggle{transition:transform .15s ease;display:inline-block;}
  #hotkeyHint{position:fixed;bottom:6px;right:10px;font-size:10px;color:#94a3b8;
    pointer-events:none;opacity:.6;user-select:none;font-family:Consolas,Menlo,monospace;z-index:5;}
  #hotkeyHint kbd{background:rgba(148,163,184,.15);border:1px solid rgba(148,163,184,.3);
    border-radius:3px;padding:0 4px;margin:0 2px;font-family:inherit;font-size:9.5px;}
  #hotkeyHint:hover{opacity:.95;pointer-events:auto;}
  /* 2026-09-15 (P1 р2, T12): переход — только прозрачность: положение (bottom) тост меняет,
     когда поднимается над подвалом открытого окна (_toastPlace в kenguru.js) — анимация
     bottom сбивала замер следующего тоста. Клик по тосту закрывает его (cursor:pointer). */
  #toast{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:#323232;color:#fff;
    padding:13px 18px;border-radius:var(--radius);font-size:13px;z-index:90;opacity:0;transition:opacity .25s;pointer-events:none;box-shadow:0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px rgba(0,0,0,.14);
    display:flex;align-items:center;gap:14px;}
  #toast.show{opacity:1;pointer-events:auto;cursor:pointer;}
  .toastUndoBtn{background:transparent;border:none;color:#8ab4ff;font-size:13px;font-weight:700;
    cursor:pointer;padding:2px 2px;white-space:nowrap;flex:none;}
  .toastUndoBtn:hover{text-decoration:underline;}
  #workFilter{padding:6px 8px;border:1px solid var(--line);border-radius:6px;font-size:12px;background:#fff;}
  .calTable{width:100%;border-collapse:collapse;table-layout:fixed;}
  .calTable th{background:#f1f3f7;border:1px solid var(--line);padding:5px;font-size:11px;}
  .calTable td{border:1px solid var(--line2);height:86px;vertical-align:top;padding:3px;overflow:hidden;}
  .calTable td.calEmpty{background:#fafbfc;}
  .calTable td.calToday{background:#eff6ff;}
  .calNum{font-size:11px;color:var(--muted);font-weight:700;}
  .calChip{font-size:10.5px;border-radius:4px;padding:2px 5px;margin-top:2px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .calChip.ord{background:#dbeafe;color:#1e3a8a;cursor:pointer;}
  .calChip.sheet{background:#e2e8f0;color:#334155;}
  .calChip.plan{background:#fef9c3;color:#854d0e;cursor:pointer;}
  .calChip.done{background:#dcfce7;color:#166534;cursor:pointer;}
  .calChip.call{background:#dbeafe;color:#1e3a8a;cursor:pointer;}
  /* плавные переходы интерфейса */
  .btn,.chip,.swatch,#syncBtn,.pill,.badge{transition:background .14s ease,border-color .14s ease,box-shadow .14s ease,color .14s ease,transform .1s ease;}
  .btn:active,.swatch:active{transform:scale(.96);}
  tbody tr,thead th{transition:background .12s ease;}
  .reqrow,.substep,.imgCell,.cxtbl tbody tr,.fld input,.fld select,.fld textarea{transition:background .12s ease,border-color .14s ease,opacity .14s ease,box-shadow .14s ease;}
  input:not([type=checkbox]):not([type=radio]):focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 2px var(--accent-tint);}
  .ovl.show{animation:fadeIn .15s ease;}
  .ovl.show .modal{animation:popIn .2s cubic-bezier(.2,.7,.3,1);}
  @keyframes fadeIn{from{opacity:0;}to{opacity:1;}}
  @keyframes popIn{from{opacity:0;transform:translateY(-14px) scale(.97);}to{opacity:1;transform:none;}}
  .imgGrid{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;}
  .imgCell{position:relative;width:92px;height:92px;border:1px solid var(--line);
    border-radius:6px;overflow:hidden;background:#fff;}
  .imgCell img{width:100%;height:100%;object-fit:cover;cursor:zoom-in;}
  .imgDel{position:absolute;top:2px;right:2px;width:18px;height:18px;border:none;
    border-radius:50%;background:rgba(220,38,38,.92);color:#fff;font-size:12px;
    line-height:1;cursor:pointer;padding:0;}
  .swatch{width:30px;height:30px;border:2px solid var(--line);border-radius:6px;cursor:pointer;
    font-size:13px;color:#9aa1ad;display:flex;align-items:center;justify-content:center;padding:0;}
  .swatch.sel{border-color:var(--accent);box-shadow:0 0 0 2px rgba(26,115,232,.2);}
  #shotPanel{position:fixed;top:0;right:0;width:42vw;height:100vh;background:#0f172a;
    z-index:75;display:none;flex-direction:column;box-shadow:-10px 0 36px rgba(0,0,0,.45);}
  #shotPanel.show{display:flex;animation:fadeIn .15s ease;}
  /* репорт №60 — потянуть за левый край, чтобы изменить ширину окна */
  #shotResize{position:absolute;left:-4px;top:0;bottom:0;width:8px;cursor:col-resize;z-index:2;}
  #shotResize:hover,#shotResize.dragging{background:rgba(255,255,255,.12);}
  #shotBar{display:flex;align-items:center;gap:8px;padding:9px 12px;border-bottom:1px solid #334155;}
  /* centering via margin:auto (НЕ justify/align-center) — иначе при зуме левый/верхний
     край изображения уходит в недоступную для прокрутки область overflow. */
  #shotWrap{flex:1;overflow:auto;padding:14px;display:flex;cursor:grab;}
  #shotWrap:active{cursor:grabbing;}
  #shotStage{position:relative;display:inline-block;margin:auto;}
  #shotImg{display:block;max-width:100%;border-radius:6px;}
  #shotOverlay{position:absolute;inset:0;pointer-events:none;}
  #shotOverlay.tool{pointer-events:auto;cursor:crosshair;}
  #rulerWidget{position:absolute;left:24px;top:48px;width:340px;height:30px;display:none;
    pointer-events:auto;cursor:move;border-radius:3px;z-index:4;
    background:rgba(255,235,59,.5);border:1px solid rgba(160,120,0,.85);
    background-image:repeating-linear-gradient(90deg,rgba(70,50,0,.55) 0 1px,transparent 1px 20px);}
  #rulerWidget .rulerEdge{position:absolute;left:0;right:0;bottom:-1px;height:2px;background:#dc2626;}
  .hl{position:absolute;background:rgba(255,235,59,.4);outline:1px solid rgba(234,179,8,.85);z-index:1;}
  #shotBar .btn.on{background:var(--accent);color:#fff;border-color:var(--accent);}
  .ovl.shotOpen{justify-content:flex-start;}
  /* репорт №83: ширина #shotPanel теперь динамическая (автоподбор/ручной resize, репорт №60) —
     --shotw синхронизируется из JS (_shotAutoFitWidth/initShotResize), иначе карточка держала
     фиксированные 53vw и наезжала на широкую (до 85vw) панель скриншота. */
  .ovl.shotOpen .modal,.ovl.shotOpen .modal.wide{margin-left:2vw;width:calc(96vw - var(--shotw,42vw));max-width:calc(96vw - var(--shotw,42vw));}
  /* репорты №242/№275/№361: #subOrdOvl/#svcSummaryOvl/#priemkiOvl задают ширину модалки
     инлайновым style= (width/max-width) — он бьёт правило выше по специфичности, поэтому здесь !important. */
  .ovl.shotOpen#subOrdOvl .modal,.ovl.shotOpen#svcSummaryOvl .modal,.ovl.shotOpen#priemkiOvl .modal,.ovl.shotOpen#ptoCardOvl .modal{margin-left:2vw!important;
    width:calc(96vw - var(--shotw,42vw))!important;max-width:calc(96vw - var(--shotw,42vw))!important;}
  code{background:#eef1f5;border:1px solid var(--line);border-radius:4px;padding:1px 5px;
    font-family:Consolas,Menlo,monospace;font-size:11.5px;word-break:break-all;}
  /* Репорт №881 (2026-09-19): колонка «1fr» = minmax(auto,1fr) — её нижняя граница берётся
     из min-content потомков. Таблица комплексов (#ovl .mbody table.cxtbl{min-width:440px},
     см. блок ≤600px) раздувала единственную колонку .cardTop/.grid2 до ~474px при экране
     390px: все поля карточки становились шире окна и обрезались справа (overflow-x:clip у
     .mbody). minmax(0,1fr) даёт колонке сжиматься; таблица прокручивается внутри своего
     .sect (overflow-x:auto). */
  @media(max-width:720px){.grid2{grid-template-columns:minmax(0,1fr);}.fld.full{grid-column:1;}
    .cardTop{grid-template-columns:minmax(0,1fr);}.cardPair{grid-template-columns:minmax(0,1fr);}.cardTriple{grid-template-columns:minmax(0,1fr);}
    .docRowHd{grid-template-columns:minmax(0,1fr);}.docLogRow,.docLogForm{grid-template-columns:minmax(0,1fr);}}
  /* ---- адаптация под телефон ---- */
  @media(max-width:600px){
    /* Репорт №119: кнопки шапки не вылезают за край — блоку кнопок разрешён
       перенос строк, у кнопок нет несжимаемого nowrap. Резерв под BUG (был здесь)
       убран репортом №405 — кнопка переехала в левый нижний угол. */
    header{padding:6px 12px;gap:8px;}
    /* отдельный мобильный размер h1 (был 15px) убран: базовый теперь фикс 13px */
    header h1 img{height:22px;}
    header .sub{display:none;}
    #syncBadge{flex-wrap:wrap;justify-content:flex-end;row-gap:6px;min-width:0;}
    /* репорты №383/№385: имя занимает свою строку целиком, кнопки (Пользователи/
       Нагрузка/Выйти) уходят на следующую СВОЕЙ группой и прижимаются вправо —
       раньше вся эта строка липла к левому краю (flex-start по умолчанию). */
    #authUserBadge{flex-wrap:wrap;min-width:0;justify-content:flex-end;}
    #authUserBadge #authUserName{max-width:46vw;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 100%;text-align:right;}
    #syncBtn{padding:6px 9px;}
    /* на телефоне дашборд снова сверху, горизонтальной лентой */
    #layout{flex-direction:column;}
    #dash{flex-direction:column;width:auto;border-right:none;
      border-bottom:1px solid var(--line);padding:10px 10px;gap:8px;}
    #dashChips{flex-direction:row;flex-wrap:wrap;gap:6px;}
    /* Репорт №469: чипы статусов (Дополнительно/В работе/Новый/Готово) убраны с мобильного
       дашборда — тесно, «Все заказы» и проблемные вкладки (Паспорта/Расстановка) остаются. */
    #dashChips .chipStatus{display:none;}
    #dashTools{flex-direction:row;flex-wrap:wrap;gap:6px;border-top:none;padding-top:0;}
    #dashTools .btn{width:auto;flex:1 1 auto;text-align:center;min-width:0;white-space:normal;}
    /* Репорт №119: длинные подписи кнопок дашборда/направлений переносятся, а не распирают кнопку */
    #dirSwitch .dirBtn,.calNavBtn{white-space:normal;min-width:0;}
    /* Баг-репорт bugmu7iuz3remy3 (2026-09-18): кнопка «Календарь монтажей» скрыта на
       мобильной версии по прямой просьбе владельца — «Задачи ПТО» (см. #ptoBtn) остаётся. */
    #calBtn{display:none;}
    /* Репорт №121: текст чипа не вылезает за границу — перенос вместо nowrap + отсечка */
    .chip{min-width:0;flex:1 1 44%;flex-direction:column;align-items:stretch;padding:6px 8px;overflow:hidden;}
    .chip .n{text-align:left;min-width:0;}
    .chip .l{white-space:normal;overflow-wrap:anywhere;}
    .chip .bar{position:static;width:auto;height:3px;border-radius:2px;margin-top:2px;}
    #toolbar{padding:9px 10px;}
    #toolbar > .searchInputWrap{width:100%;order:-1;flex:1 1 100%;}
    #toolbar .spacer{display:none;}
    #toolbar .count{width:100%;}
    #wrap{padding:0 8px 50px;overflow-x:auto;}
    table{min-width:0;}
    /* Репорт №777: «честная» ширина (width:max-content) — приём ДЕСКТОПНЫЙ. На телефоне
       колонки с prio:0 (№/Наименование/Монтаж/Отгрузка) не скрываются вовсе и в сумме
       шире экрана — таблица уехала бы в горизонтальную прокрутку там, где раньше
       вмещалась. Здесь возвращаем прежнее поведение: ширина по экрану. */
    #tbl{width:100%;}
    .ovl{padding:8px 5px;}
    /* === Окна на телефоне: фиксируем шапку и футер, прокручиваем только тело ===
       Корень проблемы: у .modal не было max-height, поэтому длинное окно росло за
       пределы экрана, а скроллилась вся .ovl — на телефоне выезжающая адресная
       строка/клавиатура прятала футер с кнопками под краем экрана. Решение: .modal
       становится flex-колонкой, ограниченной ДИНАМИЧЕСКИМ вьюпортом (100dvh, с
       фолбэком на vh). Заголовок (h2) и футер (.mfoot) не сжимаются и всегда видны;
       прокручивается только тело (.mbody). width:100%!important перебивает inline-
       ширины окон (КС-2 94vw, сравнение 97vw, диалог 460px) → нет горизонтального
       переполнения body. */
    .modal,.modal.wide,.modal.narrow{
      width:100%!important;max-width:100%!important;
      display:flex;flex-direction:column;
      max-height:calc(100vh - 16px);
      max-height:calc(100dvh - 16px);}
    .modal > h2,.modal > .mfoot{flex:0 0 auto;}
    /* Репорт №471: «Схема расстановки» на мобильном — сайдбар был фикс. 300px и на узком
       экране (~390px) съедал почти всё окно, схема сжималась в полоску. Теперь схема
       занимает ~70% ширины, палитра/кнопки управления — оставшиеся ~30% (вместо фикс. px). */
    #plCanvasWrap{flex:1 1 70%!important;}
    #plSidebar{flex:0 0 30%!important;min-width:0;}
    #plVedPanel{flex:0 0 30%!important;min-width:0;}
    .modal > .mbody{flex:1 1 auto;min-height:0;overflow-y:auto;-webkit-overflow-scrolling:touch;}
    /* Окна с нестандартной разметкой (без .mbody) — прокручиваемая область задаётся
       явно, иначе её inline max-height:72vh + шапка вылезали бы за край. */
    #ksOvl > .modal > #ksBody,#ksRegOvl > .modal > #ksRegBody{
      flex:1 1 auto!important;min-height:0;max-height:none!important;}
    .modal h2{font-size:14px;padding:12px 14px;flex-wrap:wrap;}
    .modal h2 #mTitle{min-width:0;overflow-wrap:anywhere;}
    /* Крупная зона нажатия у крестика/«свернуть»/цвета и кнопок футера (≥40px). */
    .modal h2 .x,.modal h2 .winMinBtn,.modal h2 .hdrColorBtn{min-width:40px;min-height:40px;
      display:inline-flex;align-items:center;justify-content:center;}
    .mfoot .btn{min-height:40px;}
    .mbody{padding:12px 12px;}
    .mfoot{padding:10px 12px;}
    /* Поля ввода ≥16px — iOS не зумит страницу при фокусе. */
    input:not([type=checkbox]):not([type=radio]),select,textarea{font-size:16px;}
    .reqrow{font-size:12px;}
    #toast{left:10px;right:10px;transform:none;text-align:center;}
    /* карточка заказа на телефоне: ничего не вылезает за края карточки;
       широкие блоки (номер, таблица комплексов/истории) скроллятся ВНУТРИ */
    #ovl .mbody{overflow-x:clip;}   /* clip, не hidden — не создаёт scroll-контейнер, вертикальная прокрутка карточки сохраняется */
    #ovl .mbody .sect{overflow-x:auto;-webkit-overflow-scrolling:touch;}
    #ovl .mbody table.cxtbl{min-width:440px;}
    /* Репорт №219: таблица комплексов вылезала за экран — скрываем ручку/№/фото,
       оставляем Вид/Артикул/Наименование/Кол-во/Готово/действия. */
    table.cxtbl .cxColGrip,table.cxtbl .cxColNo,table.cxtbl .cxColPhoto{display:none;}
    /* === Боковые панели — во весь экран (динамическая высота dvh) === */
    /* ⚠ Базовые правила этих панелей объявлены НИЖЕ по файлу (.imgViewerOvl ~1078,
       #orderSpecPanel ~1141, #ovl.modal-with-side-panel ~1176), поэтому при равной
       специфичности «поздняя» базовая декларация перебила бы наши — обязателен
       !important на конкурирующих свойствах (width/min/max/height/right/margin). */
    #shotPanel{width:100vw;height:100dvh;}
    .ovl.shotOpen .modal,.ovl.shotOpen .modal.wide{width:100%;max-width:100%;margin-left:0;}
    .imgViewerOvl{width:100vw!important;min-width:0!important;max-width:100vw!important;height:100dvh!important;}
    #ivCxList .ivCxHead input{font-size:16px;}
    #orderSpecPanel{width:100vw!important;right:-100vw!important;height:100dvh!important;}
    #orderSpecPanel.show{right:0!important;}
    #ovl.modal-with-side-panel .modal,#cxSpecOvl.modal-with-side-panel .modal{margin-right:0!important;}
    /* плотные панели просмотрщика PDF переносятся, чтобы не было гориз. переполнения */
    .imgViewerOvl .mvTop,.imgViewerOvl .mvTools,.imgViewerOvl .ivAnnoBar{flex-wrap:wrap;}
    .imgViewerOvl .closeX,#orderSpecPanel .ospClose{min-width:40px;min-height:40px;}
    /* === Совмещённые (tile/side-by-side) режимы НЕ делят узкий экран пополам —
       окно показывается целиком, партнёр уходит под него === */
    /* просмотрщик схемы/фото поверх окна: ужимание сводится к full-width
       (а при недостатке места _ivSqueezeOrHide и так ставит .iv-collapsed) */
    #ovl.iv-squeeze .modal,#cxSpecOvl.iv-squeeze .modal,#cxRefOvl.iv-squeeze .modal,
    #mkJournalOvl.iv-squeeze .modal,#kdMonOvl.iv-squeeze .modal{
      width:100%!important;max-width:100%!important;margin-right:0!important;}
    /* календарь + карточка заказа (calSqueeze/calOpen) — оба во всю ширину, карточка
       поверх календаря (z-index выше .ovl, но ниже .lvl2); десктопный 50/50-тайлинг
       (см. #calOvl.calSqueeze/#ovl.calOpen выше по файлу) на узком экране отменяем. */
    #calOvl.calSqueeze{right:0;}
    #calOvl.calSqueeze .modal.wide,#ovl.calOpen .modal.wide{
      width:100%!important;max-width:100%!important;margin-left:0!important;margin-right:0!important;}
    #ovl.calOpen{left:0;justify-content:center;padding-right:5px;z-index:55;}
    /* Репорт №425: 50/50-тайлинг Мониторинга КД/загрузки документации — на узком экране
       тоже отменяем (как у calSqueeze/calOpen выше), окно загрузки просто ложится поверх
       во всю ширину (уже отдельным z-index/lvl2 стеком). */
    #kdMonOvl.kdmSqueeze{right:0;}
    #kdMonOvl.kdmSqueeze .modal.wide,#docUploadOvl.kdmOpen .modal{
      width:100%!important;max-width:100%!important;margin-left:0!important;margin-right:0!important;}
    #docUploadOvl.kdmOpen{left:0;justify-content:center;padding-right:5px;}
    /* Репорт №476 + баг-репорт bugmu7hymbb1z9f (2026-09-18): 50/50-тайлинг Панели
       управления/Пользователей — на узком экране тоже отменяем, окно «Пользователи»
       ложится поверх во всю ширину. ⚠️ Комментарий выше ошибочно утверждал «свой
       z-index/lvl2» — на деле #authAdminOvl обычный .ovl (z-index:50, БЕЗ lvl2), тогда
       как #syncOvl идёт ПОЗЖЕ него в DOM: при равном z-index именно #syncOvl рисуется
       поверх и полностью закрывает «Пользователи», когда на мобильном оба легли на всю
       ширину (на десктопе баг маскировался непересекающимися половинами экрана). Явный
       z-index — тот же приём, что #ovl.calOpen{z-index:55} чуть выше. */
    #syncOvl.syncSqueeze{right:0;}
    #syncOvl.syncSqueeze .modal,#authAdminOvl.syncOpen .modal{
      width:100%!important;max-width:100%!important;margin-left:0!important;margin-right:0!important;}
    #authAdminOvl.syncOpen{left:0;justify-content:center;padding-right:5px;z-index:55;}
    /* Репорт №602: докед-панель «Папка заказа» — на узком экране во весь экран
       поверх карточки заказа (как #orderSpecPanel выше), не 50/50. */
    #orderFolderPanel{width:100vw!important;right:-100vw!important;height:100dvh!important;}
    #orderFolderPanel.show{right:0!important;}
    #ovl.orderfolder-open .modal,#svcEditOvl.orderfolder-open .modal{margin-right:0!important;}
    /* парные окна (win-tile) уже складываются стопкой в @media(max-width:900px) ниже */
    /* === Сравнение чертежей (#cmpOvl) — две панели стопкой (вертикально), не рядом === */
    #cmpOvl .modal{height:calc(100dvh - 12px)!important;max-height:calc(100dvh - 12px)!important;}
    #cmpOvl .modal > div:nth-child(2){flex-direction:column!important;}
    #cmpOvl .modal > div:nth-child(2) > div:first-child{
      border-right:none!important;border-bottom:2px solid var(--line);}
  }
  .cxSpecImages{display:flex;gap:8px;flex-wrap:wrap;margin:8px 0 12px;padding:8px;
    background:#f8fafc;border:1px solid var(--line);border-radius:6px;}
  .cxSpecImages img{height:140px;width:auto;max-width:200px;object-fit:contain;
    border:1px solid var(--line);border-radius:4px;background:#fff;cursor:zoom-in;
    transition:transform .15s ease;}
  .cxSpecImages img:hover{transform:scale(1.04);border-color:var(--accent);}
  .cxSpecImages .noimg{color:var(--muted);font-size:12px;padding:18px;text-align:center;width:100%;}
  /* Репорт №668 (2026-08-26): дата изменения файла документа на плитках галереи
     комплекса. У PDF-плиток — вторая строка под подписью (цвет плитки, приглушённо);
     у фото с диска — бейдж поверх нижнего правого угла картинки (сама картинка и её
     высота 140px не меняются; обёртка .cxPhotoWrap — только позиционирование бейджа). */
  .cxSpecImages .cxTileDate{font-size:11px;opacity:.75;white-space:nowrap;}
  .cxSpecImages .cxPhotoWrap{position:relative;display:inline-block;line-height:0;}
  .cxSpecImages .cxPhotoWrap .cxTileDate{position:absolute;right:6px;bottom:6px;line-height:1.3;opacity:1;
    background:rgba(255,255,255,.9);color:#475569;padding:1px 6px;border-radius:4px;pointer-events:none;}
  html.theme-dark .cxSpecImages .cxPhotoWrap .cxTileDate{background:rgba(30,30,34,.88);color:#cbd5e1;}
  /* Просмотр фото/схемы — боковая панель справа (PDF рендерится через pdf.js на canvas) */
  .imgViewerOvl{position:fixed;top:0;right:0;width:clamp(340px,46vw,600px);min-width:340px;max-width:95vw;height:100vh;
    background:#fff;border-left:1px solid var(--line);box-shadow:-6px 0 24px rgba(0,0,0,.18);
    z-index:200;display:none;flex-direction:column;}
  .imgViewerOvl.show{display:flex;}
  /* ручка изменения ширины (левый край) — ширина запоминается между комплексами */
  .imgViewerOvl .mvResize{position:absolute;top:0;left:0;width:9px;height:100%;cursor:ew-resize;z-index:6;touch-action:none;}
  .imgViewerOvl .mvResize::before{content:"";position:absolute;top:50%;left:2px;transform:translateY(-50%);
    width:3px;height:46px;border-radius:3px;background:var(--line);transition:background .15s;}
  .imgViewerOvl .mvResize:hover::before{background:var(--accent);}
  .imgViewerOvl .mvTop{display:flex;align-items:center;gap:6px;padding:6px 10px;
    border-bottom:1px solid var(--line);background:#f8fafc;flex-shrink:0;}
  .imgViewerOvl .mvTitle{flex:1;font-size:12px;font-weight:600;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap;color:var(--muted);}
  /* Репорт №505: линейка KENGURU PRO / KPRO — явный цветной бейдж рядом с заголовком
     (раньше различить можно было только по длинному пути в .mvPath). */
  .imgViewerOvl .mvBrand{flex-shrink:0;font-size:11px;font-weight:700;line-height:1;
    padding:4px 8px;border-radius:5px;white-space:nowrap;}
  .imgViewerOvl .mvBrand.mvBrandKen{background:#eff6ff;color:#1d4ed8;border:1px solid #93c5fd;}
  .imgViewerOvl .mvBrand.mvBrandKpro{background:#fef3c7;color:#b45309;border:1px solid #fcd34d;}
  .imgViewerOvl .mvTools{display:none;align-items:center;gap:3px;flex-shrink:0;}
  .imgViewerOvl .mvTools.show{display:flex;}
  .imgViewerOvl .mvBtn{background:#fff;border:1px solid var(--line);border-radius:5px;
    cursor:pointer;color:#334155;font-size:14px;line-height:1;padding:3px 7px;min-width:26px;}
  .imgViewerOvl .mvBtn:hover{background:#eff6ff;border-color:var(--accent);color:var(--accent);}
  .imgViewerOvl .mvBtn:disabled{opacity:.4;cursor:default;background:#fff;border-color:var(--line);color:#334155;}
  .imgViewerOvl .mvPg{font-size:12px;color:#475569;min-width:50px;text-align:center;font-variant-numeric:tabular-nums;}
  .imgViewerOvl .closeX{background:none;border:none;font-size:20px;cursor:pointer;
    color:var(--muted);padding:2px 6px;line-height:1;flex-shrink:0;}
  .imgViewerOvl .mvBody{flex:1;overflow:auto;display:flex;align-items:center;justify-content:center;padding:8px;}
  .imgViewerOvl .mvBody.pdfmode{display:block;text-align:center;background:#53575c;padding:14px;}
  /* режим увеличенной картинки: блочная раскладка со скроллом (как у PDF), чтобы зум-в-курсор работал */
  .imgViewerOvl .mvBody.imgzoom{display:block;text-align:center;background:#e5e7eb;padding:10px;}
  /* перемещение по документу зажатой ЛКМ: «хват» в режиме просмотра, когда есть прокрутка */
  .imgViewerOvl .mvBody.pdfmode:has(#ivAnno:not(.armed)),
  .imgViewerOvl .mvBody.imgzoom:has(#ivAnno:not(.armed)){cursor:grab;}
  .imgViewerOvl .mvBody.ivPanning{cursor:grabbing !important;user-select:none;}
  .imgViewerOvl .mvBody.ivPanning *{cursor:grabbing !important;}
  .imgViewerOvl .mvBody img{max-width:100%;max-height:100%;object-fit:contain;-webkit-user-drag:none;user-drag:none;user-select:none;}
  .imgViewerOvl .mvBody canvas{display:inline-block;box-shadow:0 2px 14px rgba(0,0,0,.45);background:#fff;}
  /* строка пути к найденному файлу (откуда подтянут материал) */
  .imgViewerOvl .mvPath{flex-shrink:0;font-size:10px;color:#475569;background:#eef2f7;border-bottom:1px solid var(--line);
    padding:3px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-family:Consolas,Menlo,monospace;cursor:copy;}
  .imgViewerOvl .mvPath:hover{color:var(--accent);}
  /* панель инструментов разметки */
  .imgViewerOvl .ivAnnoBar{flex-shrink:0;display:none;align-items:center;gap:4px;padding:4px 8px;
    border-bottom:1px solid var(--line);background:#fbfdff;flex-wrap:wrap;}
  .imgViewerOvl.show .ivAnnoBar{display:flex;}
  .imgViewerOvl .ivTool.active{background:var(--accent);border-color:var(--accent);color:#fff;}
  .imgViewerOvl .ivAnnoCount{font-size:11px;color:#64748b;margin-left:auto;}
  /* список комплексов под чертежом — быстрый переход к чертежу другого комплекса */
  #ivCxList{flex:0 0 auto;display:none;flex-direction:column;border-top:1px solid var(--line);background:var(--panel);}
  #ivCxList.show{display:flex;}
  #ivCxList.collapsed #ivCxRows{display:none;}
  #ivCxList .ivCxHead{display:flex;align-items:center;gap:6px;padding:5px 8px;border-bottom:1px solid var(--line);background:var(--row-alt);}
  #ivCxList .ivCxTtl{font-size:11px;font-weight:600;color:var(--text);white-space:nowrap;}
  #ivCxList .ivCxCount{font-size:10px;color:var(--muted);white-space:nowrap;}
  #ivCxList .ivCxHead input{flex:1;min-width:60px;font-size:11px;padding:4px 7px;border:1px solid var(--line);border-radius:5px;background:var(--panel);color:var(--text);font-family:inherit;}
  #ivCxList .ivCxHead .mvBtn{flex:0 0 auto;width:22px;height:22px;padding:0;font-size:10px;line-height:1;}
  #ivCxList .ivCxHead .mvBtn:disabled{opacity:.4;cursor:default;}
  #ivCxRows{max-height:30vh;overflow:auto;}
  #ivCxRows .ivCxRow{display:flex;gap:8px;align-items:baseline;padding:4px 9px;font-size:12px;cursor:pointer;border-bottom:1px solid var(--line2);}
  #ivCxRows .ivCxRow:hover{background:var(--hover);}
  #ivCxRows .ivCxRow.cur{background:#eaf2ff;}
  html.theme-dark #ivCxRows .ivCxRow.cur{background:#1e3a5f;}
  #ivCxRows .ivCxRow.loading{opacity:.5;}
  /* Репорт №395: комплексы без документа текущего типа — приглушены (но кликабельны,
     клик всё равно даёт понятный тост «не найден(а)»). */
  #ivCxRows .ivCxRow.ivCxRowMissing{opacity:.4;}
  #ivCxRows .ivCxRow.ivCxRowMissing:hover{opacity:.65;}
  #ivCxRows .ivCxRow .c{font-family:Consolas,Menlo,monospace;font-weight:600;color:var(--accent);white-space:nowrap;flex:0 0 auto;min-width:96px;}
  #ivCxRows .ivCxRow .n{color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  #ivCxRows .ivCxEmpty{padding:8px 10px;color:var(--muted);font-size:11px;}
  /* сцена с медиа + слой разметки */
  #ivStage{position:relative;display:inline-block;line-height:0;}
  /* №302: текстовый слой pdf.js поверх canvas — обычный драг выделяет текст,
     Ctrl+драг панорамирует (см. _ivInitPan). Ниже #ivAnno по z-index — пока
     активен инструмент рисования (.armed), он перехватывает клики первым. */
  #ivTextLayer{position:absolute;inset:0;overflow:hidden;line-height:1;z-index:2;
    text-align:initial;transform-origin:0 0;}
  #ivTextLayer span,#ivTextLayer br{color:transparent;position:absolute;white-space:pre;cursor:text;transform-origin:0 0;}
  #ivTextLayer ::selection{background:rgba(37,99,235,.35);}
  #ivAnno{position:absolute;inset:0;pointer-events:none;z-index:3;}
  #ivAnno.armed{pointer-events:auto;cursor:crosshair;}
  #ivAnnoSvg{position:absolute;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;}
  #ivAnnoSvg .ivShape{pointer-events:stroke;cursor:pointer;}
  #ivAnnoSvg .ivShape.fill{pointer-events:all;}
  .ivPin{position:absolute;transform:translate(-50%,-100%);pointer-events:auto;cursor:pointer;
    width:22px;height:28px;margin:0;z-index:4;filter:drop-shadow(0 1px 2px rgba(0,0,0,.4));}
  .ivPin .ivPinBody{width:22px;height:22px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);
    border:2px solid #fff;display:flex;align-items:center;justify-content:center;}
  .ivPin .ivPinNum{transform:rotate(45deg);color:#fff;font:700 11px/1 Arial,sans-serif;}
  .ivPin.st-open .ivPinBody{background:#dc2626;}
  .ivPin.st-fixed .ivPinBody{background:#d97706;}
  .ivPin.st-closed .ivPinBody{background:#16a34a;}
  .ivPin.sel{outline:2px solid var(--accent);outline-offset:2px;border-radius:50%;}
  /* всплывающий редактор замечания */
  #ivAnnoPop{position:absolute;z-index:210;width:268px;max-width:92vw;background:#fff;border:1px solid var(--line);
    border-radius:9px;box-shadow:0 10px 34px rgba(0,0,0,.28);padding:10px;display:none;font-size:12px;}
  #ivAnnoPop.show{display:block;}
  #ivAnnoPop textarea{width:100%;min-height:62px;border:1px solid var(--line);border-radius:6px;padding:6px;font:inherit;resize:vertical;box-sizing:border-box;}
  #ivAnnoPop .ivStatusRow{display:flex;gap:5px;margin:7px 0;}
  #ivAnnoPop .ivStBtn{flex:1;border:1px solid var(--line);border-radius:6px;background:#fff;cursor:pointer;padding:5px 4px;font-size:11px;color:#334155;}
  #ivAnnoPop .ivStBtn.on[data-st="open"]{background:#dc2626;border-color:#dc2626;color:#fff;}
  #ivAnnoPop .ivStBtn.on[data-st="fixed"]{background:#d97706;border-color:#d97706;color:#fff;}
  #ivAnnoPop .ivStBtn.on[data-st="closed"]{background:#16a34a;border-color:#16a34a;color:#fff;}
  #ivAnnoQuick{margin:6px 0 0;display:none;}
  #ivAnnoQuick .ivQuickTtl{font-size:10px;color:var(--muted);margin:0 0 3px;}
  #ivAnnoQuick .ivQuickWrap{display:flex;flex-wrap:wrap;gap:4px;max-height:88px;overflow:auto;}
  #ivAnnoQuick .ivQuickChip{max-width:100%;border:1px solid #bfdbfe;background:#eff6ff;color:#1e3a8a;border-radius:10px;padding:2px 8px;font-size:11px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  #ivAnnoQuick .ivQuickChip:hover{background:#dbeafe;}
  /* Мониторинг КД/ТД — три уровня строк разного цвета (раздел / подраздел / комплекс) */
  #kdmBody tr.grpRow{cursor:pointer;background:var(--panel);}
  #kdmBody tr.grpRow td{color:var(--accent-d);font-weight:700;padding:7px 9px;border-top:2px solid var(--accent);border-bottom:1px solid var(--line);}
  #kdmBody tr.grpRow:hover td{background:var(--hover);}
  #kdmBody tr.grpRow .grpToggle{color:var(--accent-d);}
  #kdmBody tr.subRow{cursor:pointer;background:var(--panel);}
  #kdmBody tr.subRow td{color:var(--text);font-weight:600;padding:5px 9px 5px 26px;border-top:1px solid var(--accent-d);border-bottom:1px solid var(--line);}
  #kdmBody tr.subRow:hover td{background:var(--hover);}
  #kdmBody tr.subRow .grpToggle{color:var(--accent-d);}
  #kdmBody tr.cxRow td{background:var(--panel);border-bottom:1px solid var(--line2);}
  #kdmBody tr.cxRow:hover td{background:var(--hover);}
  #kdmBody tr.cxRow td:first-child{color:var(--accent);}
  #kdmBody tr.cxRow td:nth-child(2){color:var(--text);}
  /* Итоговые строки таблиц — рамка-акцент сверху вместо сплошной светлой заливки
     (иначе в тёмной теме строка-«итог» оставалась светлой и текст пропадал). */
  tr.tot td,tr.totRow td{background:var(--panel);color:var(--accent-d);font-weight:700;border-top:2px solid var(--accent);}
  /* бейдж счётчика замечаний у строк списков */
  .mkBadge{display:inline-flex;align-items:center;gap:3px;background:#fee2e2;color:#b91c1c;border-radius:10px;
    padding:0 6px;font-size:10px;font-weight:700;line-height:16px;vertical-align:middle;cursor:pointer;}
  .mkBadge.allclosed{background:#dcfce7;color:#15803d;}
  #orderSpecPanel{position:fixed;top:0;right:-540px;width:520px;height:100vh;
    background:#fff;border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.12);
    z-index:60;display:flex;flex-direction:column;transition:right .25s ease;}
  #orderSpecPanel.show{right:0;}
  #orderSpecPanel .ospHead{padding:12px 16px;border-bottom:1px solid var(--line);
    display:flex;align-items:center;gap:10px;background:#f8fafc;}
  #orderSpecPanel .ospTitle{flex:1;font-weight:600;font-size:14px;}
  #orderSpecPanel .ospClose{background:none;border:none;font-size:24px;cursor:pointer;color:#64748b;}
  #orderSpecPanel .ospTabs{display:flex;gap:2px;padding:0 16px;background:#f8fafc;border-bottom:2px solid var(--line);}
  #orderSpecPanel .ospTabs .ospTab{padding:6px 12px;cursor:pointer;border:1px solid var(--line);border-bottom:none;
    background:#f1f5f9;border-radius:6px 6px 0 0;font-size:12px;font-weight:600;color:#475569;margin-bottom:-2px;}
  #orderSpecPanel .ospTabs .ospTab.active{background:#fff;color:var(--accent);border-bottom:2px solid #fff;}
  #orderSpecPanel .ospBody{flex:1;overflow:auto;padding:12px 16px;}
  /* Sticky-заголовки во всех скролл-контейнерах модалок и панелей */
  #orderSpecPanel .ospBody table thead th{position:sticky;top:0;z-index:3;background:#f1f3f7;}
  /* Репорты №605/№607 — шапка таблиц панели «Сводно по деталям» (#ospPaneAggregate) явно
     закреплена отдельным правилом (скролл-контейнер — родительский .ospBody, overflow:auto). */
  #orderSpecPanel #ospPaneAggregate table thead th{position:sticky;top:0;z-index:3;background:#f1f3f7;}
  .ovl .modal .mbody table thead th{position:sticky;top:0;z-index:3;background:#f1f3f7;}
/* Карточка заказа (репорт №43): scrollport = .mbody с padding:16px сверху — прокрученный
   контент рисуется и в padding-зоне, т.е. ВИДЕН над прилипшей шапкой. Поднимаем точку
   прилипания на высоту паддинга, чтобы шапка закрывала эту полосу. */
#ovl .modal .mbody table thead th{top:-16px;}
  #orderSpecPanel .ospPane{display:none;}
  #orderSpecPanel .ospPane.show{display:block;}
  #orderSpecPanel .ospBlk{margin-bottom:14px;border:1px solid var(--line);border-radius:6px;overflow:hidden;}
  #orderSpecPanel .ospBlk h4{margin:0;padding:8px 12px;background:#f1f5f9;font-size:13px;}
  #orderSpecPanel .ospBlk h4 .qty{color:var(--accent);font-weight:700;margin-left:6px;}
  #orderSpecPanel table{width:100%;border-collapse:collapse;font-size:11px;}
  #orderSpecPanel table th{background:#f1f5f9;padding:5px 7px;text-align:left;font-weight:600;border-bottom:1px solid var(--line);}
  #orderSpecPanel table td{padding:4px 7px;border-bottom:1px solid var(--line2);}
  #orderSpecPanel table td.r{text-align:right;font-variant-numeric:tabular-nums;}
  #orderSpecPanel .ospEmpty{padding:30px;text-align:center;color:var(--muted);}
  #orderSpecPanel .ospEditBtn{font-size:11px;padding:2px 6px;border:1px solid var(--line);border-radius:4px;
    background:#fff;cursor:pointer;color:var(--accent);margin-left:6px;}
  #orderSpecPanel .ospEditBtn:hover{background:#eff6ff;}
  .cxSpecRowBtn{font-size:11px;padding:2px 6px;border:1px solid var(--line);border-radius:4px;
    background:#fff;cursor:pointer;color:var(--accent);margin-right:4px;}
  .cxSpecRowBtn:hover{background:#eff6ff;}
  .cxSpecAllBtn{font-size:12px;margin-left:10px;padding:3px 9px;border:1px solid var(--line);
    border-radius:4px;background:#eff6ff;cursor:pointer;color:var(--accent);font-weight:600;}
  .cxSpecAllBtn:hover{background:#dbeafe;}
  #ovl.modal-with-side-panel .modal,
  #cxSpecOvl.modal-with-side-panel .modal{margin-right:520px;transition:margin-right .25s ease;}
  /* Репорт №690 (2026-08-30): докед-панель «Список комплексов» — зеркальный паттерн
     правых докед-панелей (#orderFolderPanel и т.п.), но СЛЕВА и без своей кнопки-открытия
     (всегда открыта, пока показано cxSpecOvl — см. openCxSpec/closeCxSpec в kenguru.js). */
  #cxSpecNavPanel{position:fixed;top:0;left:-400px;width:360px;height:100vh;background:var(--panel,#fff);
    border-right:1px solid var(--line);box-shadow:4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;
    flex-direction:column;transition:left .25s ease;}
  #cxSpecNavPanel.show{display:flex;left:0;}
  #cxSpecNavPanel .cxSpecNavHead{padding:11px 14px;border-bottom:1px solid var(--line);font-weight:700;
    font-size:14px;color:var(--text);background:var(--panel-2,#f8fafc);}
  #cxSpecNavPanel .cxSpecNavSearch{padding:10px 14px;border-bottom:1px solid var(--line);}
  #cxSpecNavPanel .cxSpecNavSearch input{width:100%;padding:6px 9px;border:1px solid var(--line);border-radius:7px;
    background:var(--panel);color:var(--text);font-size:13px;font-family:inherit;box-sizing:border-box;}
  #cxSpecNavPanel .cxSpecNavBody{flex:1;overflow:auto;padding:6px 8px;}
  .cxSpecNavGrp{padding:7px 8px 4px;font-weight:700;font-size:11.5px;color:var(--muted);cursor:pointer;
    user-select:none;text-transform:uppercase;letter-spacing:.02em;}
  .cxSpecNavGrp:hover{color:var(--text);}
  .cxSpecNavSub{padding:4px 8px 4px 14px;font-weight:600;font-size:11.5px;color:var(--muted);cursor:pointer;user-select:none;}
  .cxSpecNavSub:hover{color:var(--text);}
  .cxSpecNavRow{padding:5px 10px 5px 22px;font-size:12.5px;cursor:pointer;border-radius:6px;display:flex;
    gap:8px;align-items:baseline;color:var(--text);}
  .cxSpecNavRow:hover{background:var(--hover);}
  .cxSpecNavRow.cur{background:var(--accent,#2563eb);color:#fff;}
  .cxSpecNavRow .art{font-family:monospace;font-weight:600;flex:0 0 auto;}
  .cxSpecNavRow .nm{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 auto;min-width:0;}
  .cxSpecNavRow.cur .nm{color:#e0e7ff;}
  .cxSpecNavEmpty{padding:16px 10px;color:var(--muted);font-size:12.5px;text-align:center;}
  #cxSpecOvl.cxspec-nav-open .modal{margin-left:360px;transition:margin-left .25s ease;}
  @media(max-width:1240px){ #cxSpecNavPanel{display:none!important;} #cxSpecOvl.cxspec-nav-open .modal{margin-left:auto;} }
  /* Боковой просмотрщик (схема/фото) открыт — ужимаем нижележащее окно, ограничивая
     ширину остаточной полосой. Правило после modal-with-side-panel → при обоих
     классах выигрывает оно. */
  #ovl.iv-squeeze .modal,#cxSpecOvl.iv-squeeze .modal,#cxRefOvl.iv-squeeze .modal,#mkJournalOvl.iv-squeeze .modal,#kdMonOvl.iv-squeeze .modal{
    width:clamp(340px,calc(100vw - var(--ivw) - 28px),1040px);max-width:none;
    margin-right:var(--ivw);transition:margin-right .25s ease;}
  /* Ревью-фикс 2026-08-30 (репорт №690): просмотрщик документа (iv-squeeze), открытый
     ПОКА видна докед-панель «Список комплексов» (cxspec-nav-open, резервирует 360px
     слева — см. #cxSpecNavPanel) — общее правило выше знало только про правый отступ
     просмотрщика и не учитывало левый, окно карточки заезжало под обе панели. Селектор
     с 3 классами специфичнее обоих правил по отдельности → выигрывает при обоих сразу.
     _ivSqueezeOrHide (kenguru.js) при этом же состоянии передаёт доп. 360px в порог
     скрытия (extraReserved), чтобы hide-фолбэк не занижал реальную тесноту. */
  #cxSpecOvl.iv-squeeze.cxspec-nav-open .modal{
    width:clamp(340px,calc(100vw - var(--ivw) - 360px - 28px),1040px);max-width:none;
    margin-left:360px;margin-right:var(--ivw);transition:margin-left .25s ease,margin-right .25s ease;}
  /* Узкая полоса (<720px) — принудительно одноколоночная вёрстка карточки заказа
     (тот же режим, что @media max-width:720px), иначе сайдбар 320px ломает блоки. */
  #ovl.iv-narrow .modal .grid2,
  #ovl.iv-narrow .modal .cardTop,
  #ovl.iv-narrow .modal .cardPair{grid-template-columns:1fr;}
  #ovl.iv-narrow .modal .fld.full{grid-column:1;}
  /* Совсем тесно (<360px) — прячем окно целиком, оставляя спецификацию и схему. */
  #ovl.iv-collapsed,#cxSpecOvl.iv-collapsed,#cxRefOvl.iv-collapsed,#mkJournalOvl.iv-collapsed,#kdMonOvl.iv-collapsed{display:none;}

  /* ===================================================================
     ТЁМНАЯ ТЕМА. Включается классом .theme-dark на <html> (кнопка 🌙/☀ в
     шапке рядом с индикатором БД). Блок аддитивный — светлую тему не трогает.
     Сначала переопределяем палитру-переменные (этого достаточно для всего,
     что использует var(--…)), затем точечно перекрываем «жёстко» заданные
     светлые поверхности (#fff, светло-серые шапки таблиц, модалки, календарь,
     поповеры). Семантические цвета (статусы, план/выполнено/созвон, материалы)
     намеренно оставлены яркими — они читаемы и на тёмном фоне.
  =================================================================== */
  html.theme-dark{
    /* Тёмный Material в духе Google: почти-чёрные поверхности #1b1c1d/#2a2b2d,
       ярко-синий акцент #4285f4, нежно-синяя подсветка активного. */
    --bg:#1b1c1d; --panel:#2a2b2d; --line:#3c4043; --line2:#35363a;
    --text:#e8eaed; --muted:#9aa0a6; --accent:#4285f4; --accent-d:#669df6;
    --head:#161618; --row-alt:#26272a; --hover:#33343a;
    --accent-tint:#28384f;
    --shadow-1:0 1px 2px rgba(0,0,0,.4), 0 1px 3px 1px rgba(0,0,0,.25);
    --shadow-2:0 2px 6px 2px rgba(0,0,0,.3), 0 1px 2px rgba(0,0,0,.45);
    --th-bg:#26272a; --th-hover:#33343a; --surface-2:#2a2b2e;
    color-scheme:dark;
  }
  /* Чуть выше контраст синего текста (№ заказа и т.п.) на тёмном фоне. */
  html.theme-dark td.num{color:var(--accent-d);}
  /* Тёмная тема: неактивные кнопки переключателя направления */
  html.theme-dark #dirSwitch .dirBtn,
  html.theme-dark #dirSwitch .calNavBtn{background:var(--panel-2,var(--panel));color:var(--muted);}
  html.theme-dark #dirSwitch .dirBtn.active,
  html.theme-dark #dirSwitch .calNavBtn.active{background:var(--accent-tint);color:var(--accent-d);}
  html.theme-dark #dirYearSwitch .dirYearBtn{background:var(--panel-2,var(--panel));color:var(--muted);}
  html.theme-dark #dirYearSwitch .dirYearBtn.active{background:var(--accent-tint);color:var(--accent-d);}
  /* Светлые панели (#fff) → панель темы */
  html.theme-dark .chip,
  html.theme-dark .btn,
  html.theme-dark .modal,
  html.theme-dark .modal h2 .copyHdr,
  html.theme-dark .reqrow,
  html.theme-dark .substep,
  html.theme-dark #sectReq .reqCol,
  html.theme-dark .cxtbl,
  html.theme-dark .cxNotePop,
  html.theme-dark #calCellPopup,
  html.theme-dark #calCellPopup button,
  html.theme-dark #calDensityWrap button,
  html.theme-dark #workFilter,
  html.theme-dark .imgCell,
  html.theme-dark #cxOrdPop,
  html.theme-dark #orderSpecPanel,
  html.theme-dark .cxSpecImages,
  html.theme-dark .ospEditBtn,
  html.theme-dark .cxSpecRowBtn,
  html.theme-dark .rowCopyBtn{background:var(--panel);color:var(--text);}
  html.theme-dark .rowCopyBtn{color:var(--muted);border-color:var(--line);}
  html.theme-dark .rowCopyBtn:hover{background:var(--panel);}
  html.theme-dark #calGrid tbody td.note-cell .note-edit-btn{background:var(--surface-2);color:#bfd4ff;border-color:#475569;}
  /* Цветные строки (светлые пастельные метки). В ТЁМНОЙ теме строку НЕ заливаем
     целиком, а обводим цветной РАМКОЙ (цвет берётся из --rowclr, который ставит JS
     рядом с inline-заливкой). Заливку (inline background и tr-color) перебиваем
     !important, текст возвращаем к цвету темы. В СВЕТЛОЙ теме остаётся прежняя
     сплошная заливка — здесь правил нет. */
  html.theme-dark tr.clrRow,
  html.theme-dark tbody tr.clrRow td,
  html.theme-dark #cxOrdPop tr.clrRow td,
  html.theme-dark .cxtbl tr.clrRow td,
  html.theme-dark .cxtbl td.clrCell{background:transparent !important;color:var(--text) !important;}
  /* сама рамка — через границы ячеек (все таблицы border-collapse): верх/низ у всех
     ячеек строки, левая — у первой, правая — у последней; цвет = метка строки. */
  html.theme-dark tr.clrRow > td{
    border-top:2px solid var(--rowclr) !important;
    border-bottom:2px solid var(--rowclr) !important;}
  html.theme-dark tr.clrRow > td:first-child{border-left:2px solid var(--rowclr) !important;}
  html.theme-dark tr.clrRow > td:last-child{border-right:2px solid var(--rowclr) !important;}
  /* В таблице заказов первая ячейка (.selcell) скрыта, если колонку галочек убрали в «Видимые столбцы»
     (body.hideSelCol; с №989b галочки видны всем, не только админу) — левую грань рамки переносим
     на следующую видимую ячейку. */
  html.theme-dark body.hideSelCol tr.clrRow > td.selcell + td{border-left:2px solid var(--rowclr) !important;}
  /* контролы внутри цветной строки (кол-во, RFID, % …) — без пастельной заливки, под тему. */
  html.theme-dark .cxtbl tr.clrRow td.clrCell input,
  html.theme-dark .cxtbl tr.clrRow td.clrCell .qtyWrap,
  html.theme-dark .cxtbl tr.clrRow td.clrCell .qtyWrap button{
    background:var(--panel) !important;color:var(--text) !important;border-color:var(--line) !important;}
  /* Переключатель «Готово» — тёмная тема (приглушённый зелёный для отметки). */
  html.theme-dark .cxDoneBtn{background:var(--surface-2);color:var(--muted);border-color:var(--line);}
  html.theme-dark .cxDoneBtn:hover{background:var(--panel);}
  html.theme-dark .cxDoneBtn.on{background:#1c3326;color:#7fb894;border-color:#2f5740;}
  html.theme-dark .cxDoneBtn.on:hover{background:#234030;}
  /* Шапки таблиц (везде) */
  html.theme-dark thead th,
  html.theme-dark thead tr.filters th,
  html.theme-dark .cxtbl th,
  html.theme-dark #cxSumOvl .sumTbl th,
  html.theme-dark #cxOrdPop th,
  html.theme-dark #histDiffOvl .diffTbl th,
  html.theme-dark .calTable th,
  html.theme-dark #orderSpecPanel table th,
  html.theme-dark #orderSpecPanel .ospBody table thead th,
  html.theme-dark #orderSpecPanel #ospPaneAggregate table thead th,
  html.theme-dark .ovl .modal .mbody table thead th{background:var(--th-bg);color:var(--text);}
  /* Всплывающий фильтр под заголовком колонки */
  html.theme-dark thead th.colFilterCell .colFilterBox{background:var(--panel);border-color:var(--line);}
  html.theme-dark thead th.colFilterCell.has-filter{background:#16263c;}
  /* hover по сортируемым шапкам */
  html.theme-dark .sortable:hover,
  html.theme-dark #cxSumOvl .sumTbl th:hover{background:var(--th-hover);}
  /* Репорт bugms4vxylv5jlf: итог «Общий вес комплекса» — тёмная подложка вместо светлой */
  html.theme-dark .specTotRow{background:var(--th-bg);}
  /* Репорт bugms4w0rrpnp74: жёлтая подсветка деталей без веса — тёмно-янтарный фон,
     текст остаётся светлым цветом темы */
  html.theme-dark #cxRefPartsBody tr.noweight{background:#3b2f10;}
  html.theme-dark #cxRefPartsBody tr.noweight:hover{background:#4a3c15;}
  html.theme-dark #cxRefPartsBody tr.noweight td{border-color:#8a6d1a;}
  /* Светло-серые подложки → row-alt */
  html.theme-dark #calGrid tbody td.meta,
  html.theme-dark #calGrid tbody td.sticky-left,
  html.theme-dark #calGrid tbody td.dragHandle,
  html.theme-dark #calGrid tbody tr.row-mnt,
  html.theme-dark .cxtbl tbody tr:hover td,
  html.theme-dark #cxSumOvl .sumTbl tbody tr:hover td,
  html.theme-dark .cxNoteCell,
  html.theme-dark .tabBar .tab,
  html.theme-dark #orderSpecPanel .ospHead,
  html.theme-dark #orderSpecPanel .ospTabs,
  html.theme-dark #calCellPopup .rangeRow{background:var(--row-alt);color:var(--text);}
  /* Чуть светлее подложки (кнопки/вкладки/«итого») */
  html.theme-dark .qtyWrap button,
  html.theme-dark .tabBar .tab:hover,
  html.theme-dark #calCellPopup button:hover,
  html.theme-dark #cxSumOvl .sumTbl tbody tr.tot:hover td,
  html.theme-dark #orderSpecPanel .ospTabs .ospTab,
  html.theme-dark #orderSpecPanel .ospBlk h4,
  html.theme-dark .sortable:hover,
  html.theme-dark .qtyWrap button:hover{background:var(--surface-2);color:var(--text);}
  /* Активная вкладка — как панель */
  html.theme-dark .tabBar .tab.active,
  html.theme-dark #orderSpecPanel .ospTabs .ospTab.active{background:var(--panel);border-bottom-color:var(--panel);color:var(--accent-d);}
  /* Поля ввода (кроме чекбоксов/радио) */
  html.theme-dark input:not([type=checkbox]):not([type=radio]),
  html.theme-dark select,
  html.theme-dark textarea{background:var(--panel);color:var(--text);border-color:var(--line);}
  html.theme-dark input::placeholder,
  html.theme-dark textarea::placeholder{color:#8493a6;}
  /* Мелкие фоновые токены */
  html.theme-dark .pill{background:#223247;color:#cbd5e1;}
  html.theme-dark .progBar .track{background:#26344a;}
  html.theme-dark .cxbadge{background:#1e2b45;color:#bfd4ff;}
  html.theme-dark .lsBar{background:#1b2735;}
  html.theme-dark code{background:#1b2735;color:#e6eaf1;}
  html.theme-dark .empty{color:var(--muted);}
  html.theme-dark .btn.danger{border-color:#7f1d1d;}
  html.theme-dark .btn.danger:hover{background:#341a1a;}
  /* Кликабельные строки справочников/истории — тёмный hover */
  html.theme-dark #cxRefBody tr:hover td,
  html.theme-dark .catlist tr:hover td,
  html.theme-dark #cxOrdPop tr:hover td,
  html.theme-dark #histBody tr:hover td,
  html.theme-dark .cxtbl tbody tr.cxRowClickable:hover > td:not(.cxNoteCell){background:var(--hover);}
  /* Группировочные строки справочников теперь «рамочные» (var-based) — отдельные
     тёмные заливки больше не нужны (иначе вернулась бы сплошная заливка). */
  /* История: diff «было/стало» — приглушённые красный/зелёный */
  html.theme-dark #histDiffOvl .diffTbl td.before{background:#2a1618;color:#fca5a5;}
  html.theme-dark #histDiffOvl .diffTbl td.after{background:#10241a;color:#86efac;}
  /* Активная карточка услуги */
  html.theme-dark #sectReq .reqCol:not(.off){border-color:var(--accent-d);background:#13243b;}
  html.theme-dark #sectReq .reqCol:not(.off) > .reqrow > label{color:#dbe4ff;}
  /* ===== Календарь монтажей ===== */
  html.theme-dark #calGrid tbody td{border-color:var(--line);}
  html.theme-dark #calGrid tbody td.day,
  html.theme-dark #calGrid tbody tr.row-otg{background:var(--panel);color:var(--text);}
  html.theme-dark #calGrid tbody td.day:hover,
  html.theme-dark #calGrid tbody tr:hover td{background:var(--hover) !important;}
  html.theme-dark #calGrid thead th:not(.monthHead):not(.sticky-left){background:var(--th-bg);color:var(--text);}
  html.theme-dark #calGrid thead th.sticky-left{background:var(--surface-2);color:var(--text);}
  html.theme-dark #calGrid thead th.monthHead{background:#1d2836;border-bottom-color:#475569;}
  html.theme-dark #calGrid thead th.monthHead.alt{background:#243144;}
  html.theme-dark #calGrid tbody td.day.weekend{background:#241c20;}
  html.theme-dark #calGrid tbody td.day.holiday{background:#2e1b1b;}
  html.theme-dark #calGrid tbody td.day.holiday.weekend{background:#341d1d;}
  html.theme-dark #calGrid thead th.weekend{background:#241c20;}
  html.theme-dark #calGrid thead th.holiday{background:#3a1f1f !important;color:#fca5a5;}
  html.theme-dark #calGrid tbody tr.row-none{background:#2a2410;}
  html.theme-dark #calDensityWrap button:not(.active):hover{background:var(--hover);color:#bfd4ff;}
  /* Месячный «.calTable» */
  html.theme-dark .calTable td.calEmpty{background:#121a25;}
  html.theme-dark .calTable td.calToday{background:var(--hover);}
  /* план/выполнено/созвон и .calChip оставляем яркими (у них тёмный текст). */

  /* ===== Плавность интерфейса: скролл и переключения ===================
     Мягкие программные прокрутки (scrollIntoView/«к сегодня»), инерция и
     гашение «протекания» скролла на границах контейнеров, плавное проявление
     вкладок и панелей. Базовые transition для кнопок/строк/полей — выше. */
  html{scroll-behavior:smooth;}
  /* Контейнеры с программным/drag-to-pan скроллом должны прокручиваться
     МГНОВЕННО — иначе глобальный smooth (выше) анимирует каждое присваивание
     scrollLeft/scrollTop, и перетаскивание чертежа/скриншота «доезжает» рывками. */
  #calGrid,#shotWrap,#imgViewerBody,.mvBody{scroll-behavior:auto;}
  /* Инерция (тачпады/тач) + контейнерный overscroll: достигнув края модалки
     или панели, скролл не «протекает» на список под ней. */
  .mbody,.ospBody,#shotWrap,#calGrid{-webkit-overflow-scrolling:touch;overscroll-behavior:contain;}
  /* Мягкое проявление контента при переключении вкладок/панелей.
     Только opacity (без transform) — чтобы не сломать position:sticky
     внутри скролл-контейнеров. */
  .tabPane.show,.ospPane.show{animation:paneIn .18s ease;}
  @keyframes paneIn{from{opacity:0;}to{opacity:1;}}
  /* Уважаем системную настройку «уменьшить движение». */
  @media(prefers-reduced-motion:reduce){
    html{scroll-behavior:auto;}
    *,.ovl.show,.ovl.show .modal,.tabPane.show,.ospPane.show,#shotPanel.show{
      animation-duration:.001ms !important;animation-iteration-count:1 !important;
      transition-duration:.001ms !important;scroll-behavior:auto !important;}
  }

  /* ===== Сворачивание окон в нижнюю панель + парный показ при разворачивании ===== */
  /* Кнопка «свернуть» (—) в шапке окна. Ставится слева от «×» и группируется с ним. */
  .winMinBtn{border:none;background:none;cursor:pointer;font-size:20px;line-height:1;
    color:var(--muted);padding:0 4px;border-radius:6px;font-weight:700;}
  .winMinBtn:hover{background:rgba(148,163,184,.20);}
  .modal h2 .winMinBtn{margin-left:auto;}
  /* Если в шапке уже есть кнопка с margin-left:auto (журнал/мониторинг), не создаём
     вторую авто-распорку — иначе группа кнопок «расплывётся» по центру. */
  .modal h2 .winMinBtn.winMinBtnTight{margin-left:6px;}
  .modal h2 .winMinBtn + .x{margin-left:6px;}
  /* Плавное возвращение ширины модалки при выходе из парного режима (без рывка). */
  .ovl .modal{transition:width .2s ease,margin-left .2s ease,margin-right .2s ease;}
  /* Нижняя панель свёрнутых окон (как панель задач). */
  #winTaskbar{position:fixed;left:0;right:0;bottom:0;z-index:1300;display:none;gap:6px;
    padding:5px 8px;background:var(--panel,#f8fafc);border-top:1px solid var(--line);
    box-shadow:0 -4px 14px rgba(0,0,0,.12);align-items:center;overflow-x:auto;overflow-y:hidden;}
  #winTaskbar.show{display:flex;}
  #winTaskbar .wtLabel{font-size:10px;color:var(--muted);font-weight:700;margin-right:2px;
    flex-shrink:0;text-transform:uppercase;letter-spacing:.04em;}
  .wtChip{display:inline-flex;align-items:center;gap:7px;background:var(--panel,#fff);
    border:1px solid var(--line);border-radius:8px;padding:4px 6px 4px 11px;font-size:12px;
    color:var(--text,#1f2533);cursor:pointer;white-space:nowrap;box-shadow:0 1px 3px rgba(0,0,0,.10);
    flex-shrink:0;max-width:260px;transition:border-color .12s,background .12s;}
  .wtChip:hover{border-color:#94a3b8;background:rgba(148,163,184,.12);}
  .wtChip .wtIco{font-size:13px;flex-shrink:0;}
  .wtChip .wtTtl{overflow:hidden;text-overflow:ellipsis;}
  .wtChip .wtClose{border:none;background:none;cursor:pointer;color:var(--muted);font-size:15px;
    line-height:1;padding:0 3px;border-radius:4px;flex-shrink:0;}
  .wtChip .wtClose:hover{background:#fee2e2;color:#dc2626;}
  /* Тёмная тема: ховеры чипа/крестика должны быть читаемы на тёмной панели. */
  html.theme-dark .wtChip:hover{border-color:#64748b;background:rgba(148,163,184,.16);}
  html.theme-dark .wtChip .wtClose:hover{background:rgba(220,38,38,.28);color:#fca5a5;}
  /* Пока таскбар виден — освобождаем место снизу, чтобы он ничего не перекрывал. */
  body.has-wintaskbar{padding-bottom:46px;}
  body.has-wintaskbar .ovl{padding-bottom:52px;}
  body.has-wintaskbar #imgViewerOvl,
  body.has-wintaskbar #shotPanel,
  body.has-wintaskbar #orderSpecPanel{height:calc(100vh - 46px);}
  /* Серая подложка-фон под двумя окнами в парном режиме (и карточка+календарь) —
     чтобы не просвечивал список заказов под ними. Ниже окон (z 50/60), выше страницы. */
  #winTileBackdrop{position:fixed;inset:0;background:rgba(15,23,42,.55);z-index:49;display:none;}
  #winTileBackdrop.show{display:block;}
  /* Парный показ: два окна делят экран (фон прозрачный, клики ловит сама модалка). */
  .ovl.win-tile{background:transparent;pointer-events:none;}
  .ovl.win-tile .modal{pointer-events:auto;box-shadow:0 10px 26px rgba(0,0,0,.30);}
  .ovl.win-tile.win-L .modal{width:48vw!important;max-width:48vw!important;
    margin-left:1vw!important;margin-right:auto!important;transition:width .2s ease,margin .2s ease;}
  .ovl.win-tile.win-R .modal{width:48vw!important;max-width:48vw!important;
    margin-left:auto!important;margin-right:1vw!important;transition:width .2s ease,margin .2s ease;}
  /* Узкий экран: не накладываем окна друг на друга, а кладём стопкой (верх/низ). */
  @media(max-width:900px){
    .ovl.win-tile.win-L .modal,.ovl.win-tile.win-R .modal{
      width:96vw!important;max-width:96vw!important;margin:0 auto!important;
      max-height:46vh!important;overflow:auto;}
    .ovl.win-tile.win-L{align-items:flex-start;}
    .ovl.win-tile.win-R{align-items:flex-end;}
  }

/* ===== Сервисное обслуживание (ДКР): реестр МАФ + карточка МАФ ===== */
/* Реестр — сворачиваемая иерархия Округ → Район → Адрес → МАФ (как «Список ГБУ»). */
#svcRegBody .gbuOkr{margin:0 0 8px;border:1px solid var(--line);border-radius:10px;overflow:hidden;}
#svcRegBody .gbuOkrHd{display:flex;align-items:center;gap:10px;padding:9px 12px;cursor:pointer;background:var(--panel-2,#f1f5f9);font-weight:700;user-select:none;}
#svcRegBody .gbuOkrHd:hover{background:var(--hover,#e8eef6);}
#svcRegBody .gbuOkrHd .gbuCaret{transition:transform .15s;font-size:11px;color:var(--muted);}
#svcRegBody .gbuOkr.open .gbuOkrHd .gbuCaret{transform:rotate(90deg);}
#svcRegBody .gbuOkrHd .gbuCnt{margin-left:auto;font-weight:500;font-size:12px;color:var(--muted);}
#svcRegBody .gbuOkrBody{display:none;padding:4px 0 6px;}
#svcRegBody .gbuOkr.open .gbuOkrBody{display:block;}
#svcRegBody .gbuRay{padding:6px 12px 8px 14px;border-top:1px solid var(--line);}
#svcRegBody .gbuRay:first-child{border-top:none;}
#svcRegBody .gbuRayName{font-weight:600;font-size:13px;margin-bottom:2px;}
#svcRegBody .gbuRayName .gbuTag{display:inline-block;margin-left:6px;padding:0 7px;border-radius:8px;font-size:10px;font-weight:600;background:#dbeafe;color:#1d4ed8;vertical-align:middle;}
#svcRegBody .gbuNoHit{padding:18px;text-align:center;color:var(--muted);}
html.theme-dark #svcRegBody .gbuOkrHd{background:var(--panel-2,#1e293b);}
html.theme-dark #svcRegBody .gbuRayName .gbuTag{background:#1e3a5f;color:#93c5fd;}
/* верхний уровень реестра — группа по дате заявки (внутри — округа) */
#svcRegBody .gbuDate{margin:0 0 10px;border:1px solid var(--line);border-radius:11px;overflow:hidden;}
#svcRegBody .gbuDateHd{display:flex;align-items:center;gap:10px;padding:10px 13px;cursor:pointer;background:var(--panel-2,#f1f5f9);border-left:4px solid #6366f1;font-weight:700;font-size:14px;user-select:none;}
#svcRegBody .gbuDateHd:hover{background:var(--hover,#e8eef6);}
#svcRegBody .gbuDateHd .gbuCaret{transition:transform .15s;font-size:11px;color:var(--muted);}
#svcRegBody .gbuDate.open .gbuDateHd .gbuCaret{transform:rotate(90deg);}
#svcRegBody .gbuDateHd .gbuCnt{margin-left:auto;font-weight:500;font-size:12px;color:var(--muted);}
#svcRegBody .gbuDateBody{display:none;padding:7px 9px 9px;}
#svcRegBody .gbuDate.open .gbuDateBody{display:block;}
#svcRegBody .gbuDateBody .gbuOkr{margin:0 0 6px;}
#svcRegBody .gbuDateBody .gbuOkr:last-child{margin-bottom:0;}
#svcRegBody .gbuDateBody .gbuOkrHd{background:transparent;font-weight:600;}
#svcRegBody .gbuDateBody .gbuOkrHd:hover{background:var(--hover,#e8eef6);}
html.theme-dark #svcRegBody .gbuDateHd{background:var(--panel-2,#1e293b);}
.svcAddrGrp{padding:2px 0 3px 12px;}
.svcAddrName{font-size:12px;color:var(--muted);font-weight:600;margin:5px 0 2px;}
.svcAddrName .svcAddrCnt{font-weight:400;}
.svcMaf{display:flex;align-items:center;gap:10px;padding:5px 9px;margin:3px 0;border:1px solid var(--line);border-radius:8px;cursor:pointer;background:var(--panel);}
.svcMaf:hover{background:var(--line2);}
.svcMaf.svcDone{opacity:.55;}
.svcMafMain{display:flex;align-items:center;gap:10px;flex:1;min-width:0;flex-wrap:wrap;}
.svcMafRfid{font-size:11px;color:var(--muted);white-space:nowrap;font-family:Consolas,"Courier New",monospace;}
.svcMafName{font-size:13px;font-weight:500;}
.svcMafArt{font-size:11px;color:var(--muted);font-weight:400;}
.svcMafPovr{font-size:11px;color:#b91c1c;background:#fee2e2;padding:1px 7px;border-radius:8px;}
html.theme-dark .svcMafPovr{background:#3b1d1d;color:#fca5a5;}
.svcMafActs{display:flex;gap:4px;white-space:nowrap;}
.svcRfidRow{display:flex;gap:6px;align-items:center;}
.svcRfidRow input{flex:1;}
.svcForm{display:grid;grid-template-columns:repeat(6,minmax(0,1fr));gap:10px 14px;}
.svcFld{display:flex;flex-direction:column;gap:3px;font-size:12px;color:var(--muted);min-width:0;}
.svcFld>span{font-weight:600;}
.svcFld.svcC1{grid-column:span 1;}
.svcFld.svcC2{grid-column:span 2;}
.svcFld.svcC3{grid-column:span 3;}
.svcFld.svcC6,.svcFld.svcWide{grid-column:1 / -1;}
#svcExtraItems{display:flex;flex-direction:column;gap:6px;margin:4px 0;}
/* Репорт №771: поля строки стали авторастущими textarea — высоты в строке разные,
   поэтому выравниваем по верху (было center: однострочные поля болтались в середине). */
.svcExtraItem{display:grid;grid-template-columns:1fr 1fr 2fr 1fr auto;gap:8px;align-items:start;}
.svcExtraItem input,.svcExtraItem textarea{padding:6px 9px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--text);font-size:13px;font-family:inherit;box-sizing:border-box;width:100%;}
.svcExtraItem textarea.fldGrow{resize:none;overflow:hidden;min-height:0;line-height:1.35;}
@media(max-width:560px){.svcExtraItem{grid-template-columns:1fr 1fr;}}
/* Репорт №688 (2026-08-30): «+ Доп. повреждение» — повторяемая тройка Вид/Действие/Замена,
   у основного МАФ (#svcDmgExtraItems) и у каждого доп. комплекса (.svcItemDmgList). */
#svcDmgExtraItems,.svcItemDmgList{display:flex;flex-direction:column;gap:6px;margin:4px 0;}
/* Репорт №771: поля строки стали авторастущими textarea — выравнивание строки по верху. */
.svcDmgRow{display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:8px;align-items:start;}
.svcDmgRow input,.svcDmgRow textarea{padding:6px 9px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--text);font-size:13px;font-family:inherit;box-sizing:border-box;width:100%;}
.svcDmgRow textarea.fldGrow{resize:none;overflow:hidden;min-height:0;line-height:1.35;}
@media(max-width:560px){.svcDmgRow{grid-template-columns:1fr 1fr;}}
.svcItemDmgBlock{margin:-2px 0 4px 18px;padding-left:10px;border-left:2px solid var(--line);}
.svcFld input[type=text],.svcFld input[type=date],.svcFld textarea{padding:6px 9px;border:1px solid var(--line);border-radius:7px;background:var(--panel);color:var(--text);font-size:13px;font-family:inherit;box-sizing:border-box;width:100%;}
.svcFld textarea{resize:vertical;min-height:32px;}
/* Репорт №279: авторастущие поля — без ручного resize (борется с JS-подгоном) и без
   скролла до первого замера (по образцу .fld textarea.fldGrow карточки заказа) */
.svcFld textarea.fldGrow{resize:none;overflow:hidden;min-height:0;}
/* №991/A4 (2026-09-30): партии образцов-кубов на телефоне — «Наименование конструкции» (авторастущее поле) отдельной
   строкой во всю ширину под датой/кол-вом/осями/объёмом; на ПК — прежняя одна строка (сетка задана в JS инлайном) */
@media (max-width:600px){
  #betonRows .betonRowGrid{grid-template-columns:minmax(0,1fr) 52px 60px 70px 28px !important;}
  #betonRows .betonRowGrid > .betonRowName,#betonRows .betonRowHead > .betonHdName{grid-column:1 / -1;order:10;}
}
.svcFld.svcChk{flex-direction:row;align-items:center;gap:7px;grid-column:1 / -1;color:var(--text);font-size:13px;}
.svcFld.svcChk>span{font-weight:600;}
.svcFld.svcErr>span{color:#dc2626;}
.svcFld.svcErr input,.svcFld.svcErr textarea,.svcFld.svcErr .svcCombo input{border-color:#dc2626;background:#fef2f2;}
html.theme-dark .svcFld.svcErr input,html.theme-dark .svcFld.svcErr textarea,html.theme-dark .svcFld.svcErr .svcCombo input{background:#3b1d1d;}
/* шапка карточки: две даты (заявки / выезда) */
#svcEditHead{margin:2px 0 12px;}
.svcHeadRow{display:flex;gap:14px;flex-wrap:wrap;}
.svcHeadRow .svcFld{min-width:150px;}
.svcHeadRow .svcHeadRfid{flex:1 1 240px;min-width:200px;}
/* узкая карточка заявки — отступ содержимого от границ окна (шапка/тело/подвал) */
#svcEditOvl #svcEditHead,#svcEditOvl #svcEditBody{padding-left:20px;padding-right:20px;box-sizing:border-box;}
#svcEditOvl #svcEditBody{padding-bottom:6px;}
/* переиспользуемый комбобокс (каскадные / свободные списки) */
.svcCombo{position:relative;}
.svcComboList{position:absolute;top:100%;left:0;right:0;z-index:10;max-height:230px;overflow:auto;background:var(--panel);border:1px solid var(--line);border-radius:7px;box-shadow:0 6px 18px rgba(0,0,0,.16);margin-top:2px;}
/* Репорт №459: пункты выпадающих списков переносят текст по строкам (высота по
   содержимому) — длинные адреса/наименования больше не обрезаются многоточием. */
.svcComboOpt{padding:6px 10px;font-size:13px;color:var(--text);cursor:pointer;white-space:normal;overflow-wrap:anywhere;line-height:1.35;}
.svcComboOpt:hover,.svcComboOpt.active{background:var(--accent,#2563eb);color:#fff;}
html.theme-dark .svcComboList{background:var(--panel-2,#1e293b);}
/* докованная карточка комплекса сбоку от карточки заявки (тайлинг, не overlap) */
#svcCxPanel{position:fixed;top:0;right:-540px;width:500px;height:100vh;background:var(--panel,#fff);border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;flex-direction:column;transition:right .25s ease;}
#svcCxPanel.show{display:flex;right:0;}
#svcCxPanel .svcCxHead{padding:11px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px;background:var(--panel-2,#f8fafc);}
#svcCxPanel .svcCxCode{font-weight:700;font-size:15px;color:var(--accent,#2563eb);white-space:nowrap;}
#svcCxPanel .svcCxName{font-size:12px;color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#svcCxPanel .ospClose{background:none;border:none;font-size:24px;line-height:1;cursor:pointer;color:#64748b;}
#svcCxPanel .svcCxBody{flex:1;overflow:auto;padding:12px 14px;}
#svcCxPanel .cxSpecImages{margin:0 0 4px;}
#svcCxPanel .cxSpecImages img{height:120px;max-width:170px;}
#svcCxPanel .svcCxLoad,#svcCxPanel .svcCxEmpty{padding:12px;color:var(--muted);font-size:12px;}
#svcCxPanel #svcCxSpec{margin-top:14px;}
#svcCxPanel .svcCxSpecHd{font-weight:600;font-size:12px;color:var(--muted);margin-bottom:5px;}
#svcCxPanel .svcCxSpecTbl{width:100%;border-collapse:collapse;font-size:11px;}
#svcCxPanel .svcCxSpecTbl th{background:var(--panel-2,#f1f5f9);padding:4px 6px;text-align:left;border-bottom:1px solid var(--line);position:sticky;top:0;}
#svcCxPanel .svcCxSpecTbl td{padding:3px 6px;border-bottom:1px solid var(--line2,#eef2f7);}
#svcCxPanel .svcCxSpecTbl td.r,#svcCxPanel .svcCxSpecTbl th.r{text-align:right;font-variant-numeric:tabular-nums;}
/* при доке карточки комплекса модалка ужимается и сдвигается влево — окна тайлятся, не перекрываются.
   !important обязателен: у .modal инлайновый style="max-width:1080px" (без !important ужатие игнорируется и окна налезают на средних экранах ~1240–1620px). */
/* ═══ Репорт №767: левая панель «Комплексы» у окна заявки СО ═══
   Тот же слот и то же оформление, что у #cxSpecNavPanel (левая панель окна спецификации) —
   классы содержимого переиспользуются, здесь только рамка панели и сдвиг окна-хозяина.
   Панель уже, чем в спецификации (300px): у формы заявки и так есть правая панель. */
#svcCxNavPanel{position:fixed;top:0;left:-340px;width:300px;height:100vh;background:var(--panel,#fff);
  border-right:1px solid var(--line);box-shadow:4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;
  flex-direction:column;transition:left .25s ease;}
#svcCxNavPanel.show{display:flex;left:0;}
#svcCxNavPanel .cxSpecNavHead{padding:11px 14px;border-bottom:1px solid var(--line);font-weight:700;
  font-size:14px;color:var(--text);background:var(--panel-2,#f8fafc);}
#svcCxNavPanel .cxSpecNavSearch{padding:10px 14px;border-bottom:1px solid var(--line);}
#svcCxNavPanel .cxSpecNavSearch input{width:100%;padding:6px 9px;border:1px solid var(--line);border-radius:7px;
  background:var(--panel);color:var(--text);font-size:13px;font-family:inherit;box-sizing:border-box;}
#svcCxNavPanel .cxSpecNavBody{flex:1;overflow:auto;padding:6px 8px;}
#svcEditOvl.svc-nav-open .modal{margin-left:300px;transition:margin-left .25s ease;}
/* Узкий экран: сначала прячем левую панель (она справочная), правая важнее. */
@media(max-width:1240px){ #svcCxNavPanel{display:none!important;} #svcEditOvl.svc-nav-open .modal{margin-left:auto;} }
/* Ревью репорта №767: левая (300px) + форма (760px) + правая (520px) требуют ~1580px.
   На ноутбучных 1366–1600px это не помещалось — когда правый слот занят, левую панель
   убираем (она справочная, правая несёт то, ради чего кликали). */
@media(max-width:1600px){
  body:has(#svcEditOvl.svc-cx-open) #svcCxNavPanel,
  body:has(#svcEditOvl.svc-maf-open) #svcCxNavPanel,
  body:has(#svcEditOvl.orderfolder-open) #svcCxNavPanel{display:none!important;}
  #svcEditOvl.svc-nav-open.svc-cx-open .modal,
  #svcEditOvl.svc-nav-open.svc-maf-open .modal,
  #svcEditOvl.svc-nav-open.orderfolder-open .modal{margin-left:auto;}
}
/* ═══ Репорт №769: панель фото «МАФ ДО»/«МАФ ПОСЛЕ» ═══
   Правый слот — тот же, что у «Папки заявки» и «Карточки комплекса» (одновременно открыта
   всегда только одна, см. _dockCloseOthers). Оформление и ширина — как у #svcCxPanel. */
#svcMafPanel{position:fixed;top:0;right:-540px;width:500px;height:100vh;background:var(--panel,#fff);
  border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;
  flex-direction:column;transition:right .25s ease;}
#svcMafPanel.show{display:flex;right:0;}
/* шапка — как у #svcCxPanel (её правила заскоплены на свой id, поэтому дублируем) */
#svcMafPanel .svcCxHead{padding:11px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px;background:var(--panel-2,#f8fafc);}
#svcMafPanel .svcCxCode{font-weight:700;font-size:15px;color:var(--accent,#2563eb);white-space:nowrap;}
#svcMafPanel .svcCxName{font-size:12px;color:var(--muted);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#svcMafPanel .ospClose{background:none;border:none;font-size:24px;line-height:1;cursor:pointer;color:#64748b;}
#svcMafPanel .svcMafBody{flex:1;overflow:auto;padding:12px 14px;}
#svcMafPanel .svcMafBody img{max-width:100%;border-radius:8px;border:1px solid var(--line);display:block;}
#svcMafPanel .svcMafNote{color:var(--muted);font-size:12px;padding:6px 0;}
#svcMafPanel .svcMafPick{display:flex;flex-direction:column;gap:4px;margin-top:6px;}
#svcMafPanel .svcMafPick button{text-align:left;}
#svcEditOvl.svc-maf-open .modal{max-width:760px!important;margin-right:520px;transition:margin-right .25s ease,max-width .25s ease;}
@media(max-width:1240px){ #svcMafPanel{width:92vw;} #svcEditOvl.svc-maf-open .modal{margin-right:0;max-width:1080px!important;} }
#svcEditOvl.svc-cx-open .modal{max-width:760px!important;margin-right:520px;transition:margin-right .25s ease,max-width .25s ease;}
@media(max-width:1240px){ #svcCxPanel{width:92vw;} #svcEditOvl.svc-cx-open .modal{margin-right:0;max-width:1080px!important;} }
@media(max-width:1080px){ .svcForm{grid-template-columns:repeat(2,minmax(0,1fr));} .svcFld.svcC1,.svcFld.svcC2{grid-column:span 1;} .svcFld.svcC3{grid-column:span 2;} }
@media(max-width:560px){ .svcForm{grid-template-columns:1fr;} .svcFld.svcC1,.svcFld.svcC2,.svcFld.svcC3{grid-column:1 / -1;} }
/* Репорт №543: панель выбора заказа для «Задачи ПТО» — тот же докед-паттерн, что #svcCxPanel. */
#ptoOrdPickPanel{position:fixed;top:0;right:-540px;width:480px;height:100vh;background:var(--panel,#fff);border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;flex-direction:column;transition:right .25s ease;}
#ptoOrdPickPanel.show{display:flex;right:0;}
#ptoOrdPickPanel .ptoOpHead{padding:11px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px;background:var(--panel-2,#f8fafc);}
#ptoOrdPickPanel .ptoOpTitle{flex:1;font-weight:600;font-size:14px;}
#ptoOrdPickPanel .ospClose{background:none;border:none;font-size:24px;line-height:1;cursor:pointer;color:#64748b;}
#ptoOrdPickPanel .ptoOpBody{flex:1;overflow:auto;padding:12px 14px;display:flex;flex-direction:column;gap:8px;}
#ptoOrdPickPanel #ptoOrdPickSearch{padding:7px 10px;border:1px solid var(--line);border-radius:6px;background:var(--panel);color:var(--text);font-size:13px;}
#ptoOrdPickPanel .ptoOpHint{font-size:11.5px;color:var(--muted);}
#ptoOrdPickPanel .ptoOpList{display:flex;flex-direction:column;gap:4px;}
.ptoOpRow{padding:8px 10px;border:1px solid var(--line);border-radius:6px;cursor:pointer;font-size:12.5px;line-height:1.4;}
.ptoOpRow:hover{border-color:var(--accent);background:var(--hover);}
.ptoOpRow b{font-variant-numeric:tabular-nums;}
/* !important обязателен — у .modal инлайновый style="max-width:640px" (см. комментарий у svc-cx-open выше). */
#ptoCardOvl.pto-ord-open .modal{margin-right:500px!important;transition:margin-right .25s ease;}
@media(max-width:1240px){ #ptoOrdPickPanel{width:92vw;} #ptoCardOvl.pto-ord-open .modal{margin-right:0!important;} }

/* Репорт №602: докед-панель «Папка заказа на сервере» — тот же докед-паттерн, что
   #svcCxPanel/#ptoOrdPickPanel выше; крепится к карточке заказа #ovl (класс
   orderfolder-open — см. window.openOrderFolderPanel в Учёт_заказов.html). У #ovl
   .modal нет инлайнового style="max-width" (в отличие от #svcEditOvl/#ptoCardOvl),
   поэтому !important здесь не нужен — как и у соседнего #ovl.modal-with-side-panel
   (Спецификация заказа) выше по файлу. */
#orderFolderPanel{position:fixed;top:0;right:-540px;width:480px;height:100vh;background:var(--panel,#fff);border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;flex-direction:column;transition:right .25s ease;}
#orderFolderPanel.show{display:flex;right:0;}
#orderFolderPanel .ofpHead{padding:11px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px;background:var(--panel-2,#f8fafc);}
#orderFolderPanel .ofpTitle{flex:1;font-weight:600;font-size:14px;}
#orderFolderPanel .ospClose{background:none;border:none;font-size:24px;line-height:1;cursor:pointer;color:#64748b;}
#orderFolderPanel .ofpBody{flex:1;overflow:auto;padding:12px 14px;}
#orderFolderPanel .ofpName{font-weight:700;font-size:12.5px;color:var(--text);margin-bottom:6px;word-break:break-word;}
#orderFolderPanel .ofpCrumb{font-size:11.5px;color:var(--muted);margin-bottom:8px;word-break:break-all;}
#orderFolderPanel .ofpList{border:1px solid var(--line);border-radius:8px;padding:4px;min-height:60px;}
/* Репорт №671 (2026-08-26): загрузка/создание папки/удаление в «Папке заказа» —
   тулбар над списком (кнопки + подсказка про перетаскивание), подсветка списка при
   drag&drop файлов из Проводника, иконка 🗑 в строке файла/папки (admin+pto). */
#orderFolderPanel .ofpTools{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:8px;}
#orderFolderPanel .ofpToolsHint{font-size:11px;color:var(--muted);flex:1 1 auto;}
#orderFolderPanel .ofpList.ofpDrop{outline:2px dashed var(--accent,#2563eb);outline-offset:-2px;background:rgba(37,99,235,.06);}
#orderFolderPanel .ofpRowDel{flex:0 0 auto;background:none;border:1px solid transparent;border-radius:6px;padding:2px 5px;
  font-size:13px;line-height:1;cursor:pointer;opacity:.55;}
#orderFolderPanel .ofpRowDel:hover{opacity:1;border-color:#fca5a5;background:#fff5f5;}
html.theme-dark #orderFolderPanel .ofpRowDel:hover{background:#3a1d1d;}
#orderFolderPanel .ofpMissing{padding:14px 6px;font-size:12.5px;color:var(--text);line-height:1.5;}
#orderFolderPanel .ofpMissingHint{color:var(--muted);font-size:11.5px;margin:0;}
#orderFolderPanel .ofpTplBtns{display:flex;flex-wrap:wrap;gap:8px;margin-top:10px;}
#ovl.orderfolder-open .modal{margin-right:500px;transition:margin-right .25s ease;}
@media(max-width:1240px){ #orderFolderPanel{width:92vw;} #ovl.orderfolder-open .modal{margin-right:0;} }
/* Репорт №673 (2026-08-26): та же панель пристыковывается к форме заявки СО (#svcEditOvl) —
   у её .modal инлайновый style="max-width:1080px" → !important, ровно как у svc-cx-open выше.
   .ofpNote — пометка «папка лежит не по статусу заявки». */
#svcEditOvl.orderfolder-open .modal{max-width:760px!important;margin-right:500px;transition:margin-right .25s ease,max-width .25s ease;}
@media(max-width:1240px){ #svcEditOvl.orderfolder-open .modal{margin-right:0;max-width:1080px!important;} }
#orderFolderPanel .ofpNote{font-size:11.5px;color:#b45309;background:#fff7ed;border:1px solid #fed7aa;border-radius:6px;padding:6px 8px;margin-bottom:8px;line-height:1.4;}
html.theme-dark #orderFolderPanel .ofpNote{background:#3a2a12;border-color:#7c4a12;color:#fdba74;}

/* докованная мини-панель предпросмотра КС-2/КС-3 (тайлинг с #ks2Ovl, не overlap — по образцу #svcCxPanel) */
#ks2PrevPanel{position:fixed;top:0;right:-460px;width:430px;height:100vh;background:var(--panel,#fff);border-left:1px solid var(--line);box-shadow:-4px 0 16px rgba(0,0,0,.14);z-index:65;display:none;flex-direction:column;transition:right .25s ease;}
#ks2PrevPanel.show{display:flex;right:0;}
#ks2PrevPanel .ks2PrevHead{padding:10px 14px;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:9px;background:var(--panel-2,#f8fafc);}
#ks2PrevPanel .ks2PrevTitle{font-weight:700;font-size:13px;color:var(--text);flex:1;}
#ks2PrevPanel .ospClose{background:none;border:none;font-size:22px;line-height:1;cursor:pointer;color:#64748b;}
#ks2PrevPanel .ks2PrevTabs{display:flex;border-bottom:1px solid var(--line);}
#ks2PrevPanel .ks2PrevTab{flex:1;text-align:center;padding:7px 4px;font-size:12px;font-weight:600;color:var(--muted);cursor:pointer;border-bottom:2px solid transparent;}
#ks2PrevPanel .ks2PrevTab.active{color:var(--accent-d,#2563eb);border-bottom-color:var(--accent,#2563eb);}
#ks2PrevPanel .ks2PrevBody{flex:1;overflow:auto;padding:14px;background:#e9ebee;}
/* факсимиле бланка внутри мини-превью — компактная HTML-имитация КС-2/КС-3, не настоящий рендер xlsx */
.ks2Doc{background:#fff;border:1px solid #d0d3d9;box-shadow:0 1px 4px rgba(0,0,0,.1);padding:12px 14px;font-size:10.5px;line-height:1.35;color:#111;font-family:"Times New Roman",Georgia,serif;}
.ks2Doc h3{font-size:11px;text-align:center;font-weight:700;margin:0 0 2px;}
.ks2Doc .ks2DocSub{font-size:9px;text-align:right;color:#666;margin-bottom:8px;}
.ks2Doc .ks2DocRow{display:flex;gap:4px;margin-bottom:3px;border-bottom:1px dotted #ccc;padding-bottom:2px;}
.ks2Doc .ks2DocLbl{color:#666;white-space:nowrap;}
.ks2Doc .ks2DocVal{flex:1;font-weight:600;word-break:break-word;}
.ks2Doc table{width:100%;border-collapse:collapse;margin:8px 0;font-size:9.5px;}
.ks2Doc table th,.ks2Doc table td{border:1px solid #999;padding:2px 4px;}
.ks2Doc table th{background:#eef0f3;font-weight:700;}
.ks2Doc table td.num{text-align:right;font-variant-numeric:tabular-nums;}
/* репорт №357: строка самого изделия (в отличие от строк-услуг ниже) выделена
   заливкой — тёмный фон под белым текстом, а не голый color:#fff по умолчанию
   (иначе текст слился бы с белой «бумагой» .ks2Doc и стал нечитаемым). */
.ks2Doc table tr.posRow td{background:#1f6fb2;color:#fff;font-weight:600;}
.ks2Doc table tr.posRow td.num{color:#fff;}
.ks2Doc .ks2DocTotal{text-align:right;font-weight:700;margin-top:4px;}
.ks2Doc .ks2DocSign{margin-top:14px;display:flex;flex-direction:column;gap:10px;}
.ks2Doc .ks2DocSignLine{border-bottom:1px solid #333;min-height:14px;font-size:10px;padding:0 2px;}
.ks2Doc .ks2DocSignCap{font-size:8.5px;color:#777;text-align:center;}
/* при открытой мини-панели окно КС-2/КС-3 ужимается и сдвигается влево — тайлинг, не overlap.
   !important обязателен: у .modal инлайновый style="max-width:…" (без !important ужатие игнорируется). */
#ks2Ovl.ks2-with-preview .modal{max-width:1600px!important;margin-right:430px;transition:margin-right .25s ease;}
@media(max-width:1300px){ #ks2PrevPanel{width:360px;} #ks2Ovl.ks2-with-preview .modal{margin-right:360px;} }
@media(max-width:1000px){ #ks2PrevPanel{display:none!important;} #ks2Ovl.ks2-with-preview .modal{margin-right:0!important;max-width:1040px!important;} }

/* Тайлинг «Схема расстановки» + карточка комплекса из ведомости МАФ:
   расстановка прижимается влево, карточка комплекса — справа, без перекрытия.
   z-index у обоих окон одинаковый (.ovl.lvl2=60) — без явного возврата сюда
   побеждает DOM-порядок (cxSpecOvl объявлен РАНЬШЕ placeOvl в HTML), поэтому
   карточка рисовалась ПОД схемой; поднимаем её выше явным z-index. */
#placeOvl.plTileLeft .modal{width:56vw;max-width:56vw;margin-left:1vw;margin-right:auto;}
#cxSpecOvl.plTileRight{background:transparent;z-index:62;}
#cxSpecOvl.plTileRight .modal{width:41vw;max-width:41vw;margin-left:auto;margin-right:1vw;}
/* Индивидуальный состав комплекса на схеме — диалог поверх «Схемы расстановки» */
#plCustPartsOvl{z-index:63;}

/* ===== БАГ-РЕПОРТЫ (кнопка «🐞 BUG» + окно репорта + журнал) =====
   Кнопка живёт в зазоре под шапками окон (padding .ovl = 26px снизу тоже — 2-значный
   shorthand «26px 14px») и ПОВЕРХ всех окон: z=300 > mkBulkOvl(250). Лестница окон
   репортов: #bugOvl 280, #bugJrnOvl 284, прицел 288, зум скриншота 290 —
   Escape-цепочка закрывает в том же порядке (зум → журнал → репорт).
   Репорт №405: кнопка перенесена из правого верхнего угла в левый нижний (там же
   раньше был резерв header{padding-right} — убран, см. правки выше по файлу). */
/* Репорт №133: кнопка BUG — белая (была красной #dc2626). */
#bugBtn{position:fixed;bottom:3px;left:8px;z-index:300;height:20px;line-height:1;
  display:flex;align-items:center;gap:3px;padding:0 9px;font-size:10.5px;font-weight:700;
  letter-spacing:.4px;background:#fff;color:#b91c1c;border:1px solid #cbd5e1;
  border-radius:10px;box-shadow:0 1px 3px rgba(0,0,0,.35);opacity:.9;transition:opacity .15s;}
#bugBtn:hover{opacity:1;}
/* «Панель задач» свёрнутых окон (#winTaskbar) занимает всю нижнюю полосу поверх
   кнопки (z=1300>300) — поднимаем BUG над ней, пока она видна. */
body.has-wintaskbar #bugBtn{bottom:50px;}
/* Репорт №696: при открытом ЖУРНАЛЕ (#bugJrnOvl) кнопка больше НЕ прячется — можно
   завести новый репорт, не закрывая журнал (openBugModal сам закроет журнал).
   Прячем только при открытой ФОРМЕ репорта. */
body:has(#bugOvl.show) #bugBtn{display:none;}
#bugOvl{z-index:280;}
#bugJrnOvl{z-index:284;}
#bugOvl .mbody{display:flex;flex-direction:column;gap:12px;}
.bugField>label{display:block;font-size:11.5px;color:var(--muted);margin-bottom:4px;font-weight:600;}
.bugCtxRow{display:flex;gap:8px;align-items:center;}
.bugCtxRow input{flex:1;padding:7px 9px;border:1px solid var(--line);border-radius:8px;font-size:13px;background:var(--panel);color:inherit;}
#bugShotBox{border:1px dashed var(--line);border-radius:10px;background:var(--row-alt);
  min-height:60px;max-height:300px;overflow:auto;display:flex;align-items:center;justify-content:center;position:relative;}
#bugShotWrap{position:relative;line-height:0;}
#bugShotWrap img{max-width:100%;display:block;}
#bugShotRect{position:absolute;border:2px solid #dc2626;background:rgba(220,38,38,.10);
  border-radius:2px;pointer-events:none;box-shadow:0 0 0 1px rgba(255,255,255,.5);}
#bugShotEmpty{color:var(--muted);font-size:12px;padding:20px;text-align:center;}
.bugShotBtns{display:flex;gap:8px;align-items:center;margin-top:6px;flex-wrap:wrap;}
.bugHint{font-size:11px;color:var(--muted);}
/* №349: скриншот в форме «Список заявок на приёмку» — тот же паттерн, что у баг-репортов */
#priemkiShotBox{border:1px dashed var(--line);border-radius:10px;background:var(--row-alt);
  min-height:50px;max-height:220px;overflow:auto;display:flex;align-items:center;justify-content:center;position:relative;}
#priemkiShotWrap{position:relative;line-height:0;}
#priemkiShotWrap img{max-width:100%;display:block;}
#priemkiShotEmpty{color:var(--muted);font-size:12px;padding:16px;text-align:center;}
.bugFieldHidden{display:none;}
.bugSteps{border:1px solid var(--line);border-radius:8px;background:var(--panel);
  font-size:11.5px;font-family:Consolas,Menlo,monospace;padding:7px 10px;color:var(--muted);
  max-height:110px;overflow:auto;white-space:pre-line;}
#bugText{width:100%;box-sizing:border-box;padding:8px 10px;border:1px solid var(--line);
  border-radius:8px;font-size:13px;font-family:inherit;resize:vertical;background:var(--panel);color:inherit;}
.bugFoot{display:flex;align-items:center;gap:12px;justify-content:flex-end;}
#bugFootNote{color:#dc2626;flex:1;}
/* режим прицеливания */
#bugPickHl{position:fixed;z-index:288;pointer-events:none;border:2px solid #dc2626;
  background:rgba(220,38,38,.08);border-radius:3px;display:none;box-shadow:0 0 0 1px rgba(255,255,255,.6);}
#bugPickBar{position:fixed;z-index:288;top:10px;left:50%;transform:translateX(-50%);
  background:#dc2626;color:#fff;font-size:12.5px;font-weight:600;padding:7px 14px;
  border-radius:9px;box-shadow:0 3px 10px rgba(0,0,0,.3);pointer-events:none;white-space:nowrap;}
body.bugAiming, body.bugAiming *{cursor:crosshair !important;}
/* зум скриншота из журнала */
#bugZoomOvl{position:fixed;inset:0;z-index:290;background:rgba(15,17,20,.85);display:none;
  align-items:center;justify-content:center;padding:24px;cursor:zoom-out;}
#bugZoomOvl.show{display:flex;}
#bugZoomOvl img{max-width:96vw;max-height:94vh;border-radius:6px;box-shadow:0 8px 40px rgba(0,0,0,.6);background:#fff;}
/* журнал */
.bugJrnRow{display:flex;gap:12px;border:1px solid var(--line);border-radius:10px;
  padding:10px 12px;margin-bottom:10px;background:var(--panel);align-items:flex-start;}
.bugJrnRow.fixed{opacity:.62;}
.bugJrnRow.archived{opacity:.5;}
.bugJrnThumb{flex:0 0 130px;min-height:60px;display:flex;align-items:center;justify-content:center;
  font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:6px;
  background:var(--row-alt);overflow:hidden;}
.bugJrnThumb img{max-width:130px;max-height:90px;display:block;cursor:zoom-in;}
.bugJrnMid{flex:1;min-width:0;}
.bugJrnHead{display:flex;gap:10px;align-items:baseline;flex-wrap:wrap;}
.bugJrnHead b{font-size:13px;}
.bugJrnNo{font-size:11px;color:var(--muted);font-weight:700;}
.bugJrnDate{font-size:11px;color:var(--muted);margin-left:auto;white-space:nowrap;}
/* Репорт №696 (2026-08-30): ФИО заявителя */
.bugJrnFio{font-size:11px;color:var(--muted);}
.bugJrnText{font-size:12.5px;margin-top:4px;white-space:pre-wrap;word-break:break-word;}
.bugJrnTextBox .bugJrnText{display:inline;}
.bugJrnTextBox .btn{margin-top:4px;margin-left:8px;vertical-align:baseline;}
.bugJrnTextEdit{width:100%;min-height:60px;font-size:12.5px;font-family:inherit;padding:6px 8px;
  border:1px solid var(--line);border-radius:6px;background:var(--panel);color:inherit;resize:vertical;
  box-sizing:border-box;margin-top:4px;}
.bugJrnSteps{margin-top:6px;font-size:11px;color:var(--muted);}
.bugJrnSteps summary{cursor:pointer;user-select:none;}
.bugJrnSteps>div{font-family:Consolas,Menlo,monospace;margin-top:4px;line-height:1.5;}
.bugJrnSel{margin-top:5px;font-size:10.5px;color:var(--muted);font-family:Consolas,Menlo,monospace;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.bugJrnAct{display:flex;flex-direction:column;gap:6px;flex:0 0 auto;}
.bugJrnAct .btn.ok{background:#0b6b3a;color:#fff;border-color:#0b6b3a;}
/* Репорт №115: режим согласования заявок — бейджи статусов, селектор, фильтр */
.bugJrnStatus{font-size:10px;font-weight:700;border-radius:8px;padding:2px 8px;display:inline-block;}
.bugJrnStatus.stNew{background:#fef3c7;color:#92400e;}
.bugJrnStatus.stApp{background:#dbeafe;color:#1d4ed8;}
.bugJrnStatus.stArc{background:#e2e8f0;color:#475569;}
.bugJrnStatus.stFix{background:#dcfce7;color:#166534;}
/* Репорт №171: переключатель заказчика (Кенгуру ⇄ Промпарк) в письме на образцы бетона */
.betonCustSw{display:flex;gap:4px;margin-top:4px;}
.betonCustSw .btn.cur{background:var(--accent);color:#fff;border-color:var(--accent);}
/* Репорт №157: подсветка «🐞 Репорты», пока есть заявки «На согласовании» (как #authUsersBtn.authHasPending) */
#bugJrnDashBtn.bugHasNew{background:#fef3c7;border-color:#f59e0b;color:#92400e;font-weight:700;}
/* Репорт №141: переключатель статусов (колонка кнопок) вместо выпадающего списка */
.bugJrnStSw{display:flex;flex-direction:column;gap:3px;}
.bugJrnStSw .stBtn{font-size:10.5px;font-weight:600;padding:3px 9px;border:1px solid var(--line);
  border-radius:8px;background:var(--panel);color:var(--muted);cursor:pointer;text-align:left;white-space:nowrap;}
.bugJrnStSw .stBtn:hover{border-color:var(--accent);color:var(--accent);}
.bugJrnStSw .stBtn.cur.stNew{background:#fef3c7;color:#92400e;border-color:#f59e0b;}
.bugJrnStSw .stBtn.cur.stApp{background:#dbeafe;color:#1d4ed8;border-color:#3b82f6;}
.bugJrnStSw .stBtn.cur.stArc{background:#e2e8f0;color:#475569;border-color:#94a3b8;}
.bugJrnStSw .stBtn.cur.stFix{background:#dcfce7;color:#166534;border-color:#22c55e;}
.bugJrnFilter{display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin-bottom:12px;
  position:sticky;top:0;z-index:2;background:var(--panel);padding:4px 0 8px;border-bottom:1px solid var(--line);}
.bugJrnFilter .btn.cur{background:var(--accent);color:#fff;border-color:var(--accent);}
/* Репорт №389: на телефоне строка журнала — колонкой (было в ряд: миниатюра 130px +
   колонка статусов (flex:0 0 auto, не сжимаются) оставляли тексту <100-150px). */
@media(max-width:600px){
  .bugJrnRow{flex-direction:column;}
  .bugJrnThumb{flex:0 0 auto;align-self:flex-start;max-width:130px;}
  .bugJrnMid{width:100%;}
  .bugJrnAct{flex-direction:row;flex-wrap:wrap;width:100%;}
  .bugJrnStSw{flex-direction:row;flex-wrap:wrap;flex:1;}
}
.theme-dark #bugShotBox{background:rgba(148,163,184,.08);}
.theme-dark #priemkiShotBox{background:rgba(148,163,184,.08);}
.theme-dark #bugZoomOvl img{background:#1e2430;}

/* Репорты bugms4vr3aal6k8 + bugms4waewndff3: подвал карточки заказа (Сохранить/
   Отмена/Удалить) закреплён внизу, и под ним НЕ просвечивает продолжение карточки.
   Прежний sticky-футер «плыл» поверх середины карточки (скроллилась вся .ovl) —
   теперь модалка = флекс-колонка высотой не более .ovl (его паддинги, в т.ч.
   +46px таскбара свёрнутых окон, учитываются автоматически), скроллится только
   .mbody. На телефоне (≤600px) то же делает общий мобильный блок для всех .modal. */
@media(min-width:601px){
  #ovl .modal{display:flex;flex-direction:column;max-height:100%;}
  #ovl .modal>h2,#ovl .modal>.mfoot{flex:0 0 auto;}
  #ovl .modal>.mbody{flex:1 1 auto;min-height:0;overflow-y:auto;}
}

/* Репорт bugms4xhsnn4yjc: окно АОСР — тот же паттерн, что карточка выше:
   модалка = флекс-колонка, скроллится только #aosrBody (инлайн max-height:74vh
   перебивается), футер #aosrFoot (.mfoot) прижат к низу вне скролла; sticky-футеры
   внутри тела убраны в JS. Без media: на телефоне общий мобильный блок делает
   .modal флекс-колонкой, а этим правилам он не противоречит. */
#aosrOvl .modal{display:flex;flex-direction:column;max-height:100%;}
#aosrOvl .modal>h2,#aosrOvl .modal>div:not(#aosrBody){flex:0 0 auto;}
#aosrOvl .modal>#aosrBody{flex:1 1 auto;min-height:0;max-height:none!important;}
#aosrOvl #aosrFoot:empty{display:none;}

/* ===================================================================
   АУДИТ ТЁМНОЙ ТЕМЫ (2026-07-28): точечные контраст-фиксы поверх блока
   «ТЁМНАЯ ТЕМА» выше. Светлую тему не трогают. Инлайн-стили из JS/HTML
   перебиваются либо переменными с fallback (правится сам инлайн в JS),
   либо [style*=…]-селекторами с !important. =========================== */
html.theme-dark{--danger:#f28b82;--warn-strong:#fbbf24;--err-strong:#f87171;--chip-all:#e8eaed;
  --lswarn-bg:rgba(220,53,69,.18);--lswarn-fg:#fca5a5;}
/* таблица заказов: выделенная чекбоксом строка (админ) */
html.theme-dark tr.selrow{background:#3a3120 !important;}
/* метка процента прогресс-бара */
html.theme-dark .progBar .lbl{color:var(--muted);}
/* календарь: drag-выделение диапазона дней */
html.theme-dark #calGrid tbody td.day.range-sel{background:#1e3a5f !important;}
/* календарь: заголовок попапа ячейки дня */
html.theme-dark #calCellPopup .hdr{color:var(--text);}
/* календарь: метка типа строки «Монтаж» (парная row-otg уже на var(--accent-d)) */
html.theme-dark #calGrid tbody tr.row-mnt td.meta.row-type{color:#fbbf24;}
/* календарь: плашка «выбрано ячеек» */
html.theme-dark #calSelHint{background:var(--accent-tint) !important;border-color:#3c5170 !important;color:var(--accent-d) !important;}
html.theme-dark #calSelHint a{color:var(--accent-d) !important;}
/* карточка заказа: номер позиции и выбранные строки таблицы комплексов */
html.theme-dark .cxtbl .cxNumCell{color:var(--muted);}
html.theme-dark .cxtbl tbody tr.cxSelRow > td{background:#1e3a5f !important;}
/* поповер примечания позиции: рамка выбранного свотча */
html.theme-dark .cxNotePop .sw.sel{border-color:var(--text);}
/* поповер «заказы с комплексом» в сводке */
html.theme-dark #cxOrdPop .ph{color:var(--text);}
html.theme-dark #cxOrdPop .ph .sub{color:var(--muted);}
html.theme-dark #cxOrdPop .close{color:var(--muted);}
html.theme-dark #cxSumOvl .sumFilter .lbl{color:var(--muted);}
/* вспышка-подсветка строки при переходе из поповера */
@keyframes rowFlashDark{0%{background:#4a3a17;}100%{background:transparent;}}
html.theme-dark tr.rowHighlight td{animation-name:rowFlashDark;}
/* карточка заказа: название выключенной услуги */
html.theme-dark #sectReq .reqCol.off > .reqrow > label{color:var(--muted);}
/* просмотрщик документов: шапка + счётчик страниц + попап замечания */
html.theme-dark .imgViewerOvl .mvTop{background:var(--th-bg);}
html.theme-dark .imgViewerOvl .mvPg{color:var(--muted);}
html.theme-dark #ivAnnoPop{background:var(--panel);}
html.theme-dark #ivAnnoDel{color:#f87171 !important;}
/* панель спецификации заказа: кнопки */
html.theme-dark #orderSpecPanel .ospEditBtn{background:var(--panel);color:var(--accent-d);}
html.theme-dark #orderSpecPanel .ospEditBtn:hover{background:var(--hover);}
html.theme-dark .cxSpecRowBtn:hover{background:var(--hover);}
html.theme-dark .cxSpecAllBtn{background:var(--accent-tint);color:var(--accent-d);}
html.theme-dark .cxSpecAllBtn:hover{background:#324a68;}
/* СО: подпись поля с ошибкой валидации */
html.theme-dark .svcFld.svcErr>span{color:#f87171;}
/* баг-репорт: красная приписка в футере */
html.theme-dark #bugFootNote{color:#f87171;}
/* гейт входа: текст ошибки логина/регистрации */
html.theme-dark .authErr{color:#f87171;}
/* инлайн-предупреждения #b45309 в HTML-разметке (браузер не поддерживается / пояснение «Детали») */
html.theme-dark p[style*="#b45309"],html.theme-dark b[style*="#b45309"]{color:#fbbf24 !important;}
/* журнал замечаний: панель массовых действий */
html.theme-dark #mkBulkActions{background:var(--accent-tint) !important;border-color:#3c5170 !important;}
/* мониторинг КД: цветные заголовки колонок */
html.theme-dark #kdMonOvl thead th[style*="2563eb"]{color:#8ab4f8 !important;}
html.theme-dark #kdMonOvl thead th[style*="7c3aed"]{color:#c0a5f8 !important;}
/* ИИ-проверка: фиолетовые панели «разбить объём» + их подписи, даты/счётчики в таблице */
html.theme-dark #aiChkSplitBar,html.theme-dark #aiPaspChkSplitBar{background:#292438 !important;border-color:#4a3f6b !important;}
html.theme-dark #aiChkSplitBar [style*="5b21b6"],html.theme-dark #aiPaspChkSplitBar [style*="5b21b6"]{color:#c4b5fd !important;}
html.theme-dark #aiPaspChkBody td[style*="7c3aed"]{color:#a78bfa !important;}
html.theme-dark #aiPaspChkBody span[style*="dc2626"]{color:#f87171 !important;}
/* ДКР: «— не заполнено —» в закрывающих документах; КС-2: пометка правок индексов */
html.theme-dark #dkrDocOvl [style*="color:#b91c1c"]{color:#fca5a5 !important;}
html.theme-dark #ksDopInfo [style*="color:#c0392b"]{color:#fca5a5 !important;}
/* переменная «✓ найден» для мониторинга/ИИ-окон (инлайн var(--ok-strong,#15803d)) */
html.theme-dark{--ok-strong:#4ade80;}
/* карточка заказа: кнопка «✎ примечание» в таблице позиций */
html.theme-dark .cxtbl .cxNoteBtn{color:var(--muted);}
/* СО: докованная карточка комплекса — шапка/крестик/шапки таблиц */
html.theme-dark #svcCxPanel .svcCxHead{background:var(--row-alt);}
html.theme-dark #svcCxPanel .ospClose{color:var(--muted);}
html.theme-dark #svcCxPanel .svcCxSpecTbl th{background:var(--th-bg);}
/* Репорт №602: докед-панель «Папка заказа» — шапка/крестик (дерево переиспользует
   те же строки/кнопки, что #fsBrowserOvl — уже themed отдельно). */
html.theme-dark #orderFolderPanel .ofpHead{background:var(--row-alt);}
html.theme-dark #orderFolderPanel .ospClose{color:var(--muted);}
/* КС-2: мини-панель предпросмотра — шапка/крестик («бумагу» .ks2Doc не трогаем) */
html.theme-dark #ks2PrevPanel .ks2PrevHead{background:var(--row-alt);}
html.theme-dark #ks2PrevPanel .ospClose{color:var(--muted);}
/* Репорт №690: докед-панель «Список комплексов» — шапка */
html.theme-dark #cxSpecNavPanel .cxSpecNavHead{background:var(--row-alt);}
/* Ревью репортов №767/№769: у новых панелей тоже нужна тёмная тема — переменная --panel-2
   в проекте не объявлена, светлый фон задан фолбэком, поэтому шапки перекрываются точечно
   (тот же приём, что у #svcCxPanel/#cxSpecNavPanel выше). */
html.theme-dark #svcCxNavPanel .cxSpecNavHead{background:var(--row-alt);}
html.theme-dark #svcMafPanel .svcCxHead{background:var(--row-alt);}
html.theme-dark #svcMafPanel .ospClose{color:var(--muted);}
/* мониторинг КД: заголовок колонки «Изображение» */
html.theme-dark #kdMonOvl thead th[style*="0891b2"]{color:#78d9ec !important;}

/* ===== СО: окно «Сервисное обслуживание» — шире + отступы от краёв (репорт bugms56ibhtqvis) ===== */
/* Контент этого окна (тулбар + реестр) — прямые дети .modal без обёртки .mbody,
   поэтому строки и кнопки лежали вплотную к границе окна. */
#svcRegOvl .modal{max-width:1480px;}
#svcRegOvl .modal>div{margin-left:18px;margin-right:18px;}
#svcRegOvl #svcRegBody{margin-bottom:16px;padding-right:8px;}

/* ===== ДОКУМЕНТООБОРОТ ЗАКАЗА: секция «📑 Документы» в карточке (только Kenguru) ===== */
.docList{display:flex;flex-direction:column;gap:6px;margin-top:8px;}
.docRow{border:1px solid var(--line);border-radius:6px;background:var(--panel);}
.docRow.overdue{border-color:#dc2626;}
.docRow.closed{opacity:.75;}
.docRowHd{display:grid;grid-template-columns:16px 22px minmax(0,1fr) 150px 140px minmax(0,120px) auto auto;
  gap:8px;align-items:center;padding:6px 10px;}
/* репорт №403: ручка перетаскивания — тот же паттерн, что .cxGrip у позиций заказа */
.docGrip{display:inline-block;cursor:grab;color:#94a3b8;font-size:15px;line-height:1;user-select:none;}
.docGrip:active{cursor:grabbing;}
.docRow.dragover{box-shadow:inset 0 0 0 2px var(--accent);}
/* Репорт №221: на телефоне 7 колонок в один ряд не помещаются и наезжают друг на
   друга — стек в одну колонку на всю ширину. Правило намеренно НЕ в блоке
   @media(max-width:720px) выше (там уже есть .docRowHd{grid-template-columns:1fr}):
   та строка идёт РАНЬШЕ этого безусловного правила по тексту файла и при равной
   специфичности проигрывает каскад — переопределение должно идти позже. */
@media(max-width:600px){
  .docRowHd{grid-template-columns:1fr;}
}
.docChk{display:inline-flex;align-items:center;justify-content:center;width:18px;height:18px;
  border:1px solid var(--line);border-radius:4px;font-size:12px;color:var(--muted);padding:0;cursor:pointer;background:var(--bg);flex:none;}
.docChk.on{background:#16a34a;border-color:#16a34a;color:#fff;}
.ofPdfWarning{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-left:5px;border-radius:50%;background:#facc15;color:#78350f;font-size:12px;font-weight:800;flex:none;cursor:help;}
.docLbl{border:1px solid transparent;background:transparent;font-size:13px;padding:3px 4px;
  border-radius:4px;min-width:0;color:inherit;}
.docLbl:hover,.docLbl:focus{border-color:var(--line);background:var(--bg);}
.docStage{font-size:12px;padding:3px 4px;border-radius:4px;border:1px solid var(--line);
  background:var(--bg);color:inherit;min-width:0;}
.docPlan{font-size:12px;min-width:0;box-sizing:border-box;}
.docHolder{font-size:12px;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.docRow.overdue .docPlan{outline:1px solid #dc2626;border-radius:3px;}
.docExpBtn{white-space:nowrap;}
.docRowBody{border-top:1px solid var(--line);padding:8px 10px;display:flex;flex-direction:column;gap:6px;}
.docLogList{display:flex;flex-direction:column;gap:4px;}
.docLogRow{display:grid;grid-template-columns:140px minmax(0,1fr) minmax(0,1fr) auto;gap:6px;align-items:center;}
.docLogRow input,.docLogForm input{font-size:12px;min-width:0;box-sizing:border-box;}
/* Репорт №711: «Комментарий» — авторастущая textarea (высота подгоняется _taAutoGrow) */
.docLogRow textarea.docLogNote,.docLogForm textarea.docLogNote{font-size:12px;min-width:0;
  box-sizing:border-box;resize:none;overflow:hidden;min-height:0;line-height:1.35;
  font-family:inherit;padding:3px 6px;border:1px solid var(--line);border-radius:4px;
  background:var(--bg);color:inherit;}
.docLogEmpty{font-size:12px;color:var(--muted);}
.docLogForm{display:grid;grid-template-columns:140px minmax(0,1fr) minmax(0,1fr) auto;gap:6px;
  align-items:center;padding-top:6px;border-top:1px dashed var(--line);}
.docBtnRow{display:flex;gap:8px;flex-wrap:wrap;margin-top:10px;align-items:center;}
.docAddSel{font-size:12px;padding:4px 6px;border-radius:4px;border:1px solid var(--line);
  background:var(--bg);color:inherit;}
.docDirBox{margin-top:10px;border:1px solid var(--line);border-radius:6px;padding:8px 10px;
  background:var(--bg);display:flex;flex-direction:column;gap:6px;}
.docDirCap{font-size:11px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.4px;}
/* Репорт №165: сетка была 3-колоночной (22px под спейсер), а строки типов кладут
   2 элемента — имя сжималось в 22px, 🗑 растягивалась на всю ширину. 2 колонки. */
.docDirRow{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:center;}
.docDirName{font-size:12px;padding:3px 6px;border-radius:4px;border:1px solid var(--line);
  background:var(--panel);color:inherit;min-width:0;box-sizing:border-box;}
html.theme-dark .docChk{background:var(--panel);}
html.theme-dark .docLbl:hover,html.theme-dark .docLbl:focus{background:var(--panel);}
/* Этап документа — кнопка-переключатель (репорт №25): цвет по текущему этапу */
button.docStage{cursor:pointer;text-align:center;font-weight:600;user-select:none;white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;}
button.docStage.st-none{color:var(--muted);}
button.docStage.st-prep{background:#e3ecfa;color:#1d4f9c;border-color:#b9cff0;}
button.docStage.st-handed{background:#fdf3d7;color:#8a6d1a;border-color:#ecd9a0;}
button.docStage.st-signing{background:#f3e8fb;color:#6b2fa0;border-color:#dcc3f0;}
button.docStage.st-closed{background:#e1f5e6;color:#1d7a3d;border-color:#bfe4c8;}
html.theme-dark button.docStage.st-prep{background:#1c3354;color:#9ec4f5;border-color:#2c528a;}
html.theme-dark button.docStage.st-handed{background:#3d3316;color:#e8c96a;border-color:#5c4d20;}
html.theme-dark button.docStage.st-signing{background:#33204a;color:#cfa6f2;border-color:#4f3372;}
html.theme-dark button.docStage.st-closed{background:#173425;color:#7fd89d;border-color:#245c3a;}
/* Подстроки «7 суток»/«28 суток» протокола бетона (репорты bugmscxhsf45z07/bugmscxjf93xd1p) */
.docBetonSub{display:flex;flex-direction:column;gap:4px;padding:0 10px 8px 30px;}
.docBetonRow{display:grid;grid-template-columns:64px auto 140px minmax(0,1fr);gap:8px;align-items:center;}
/* Репорт №568: «Получено»/«Подписано» — тот же .docBetonSub-контейнер, своя сетка
   (без 4-й колонки «№ протокола» — тут её нет). */
.docHandoverRow{display:grid;grid-template-columns:88px auto 140px;gap:8px;align-items:center;}
.docBetonCap{font-size:12px;color:var(--muted);font-weight:600;white-space:nowrap;}
.docBetonNum{font-size:12px;padding:3px 6px;border-radius:4px;border:1px solid var(--line);
  background:var(--bg);color:inherit;min-width:0;box-sizing:border-box;}
/* Репорт №403: связи между документами заказа («Связать» + список зависимостей) */
.docDeps{padding:0 10px 8px 30px;}
.docDepsLine{display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.docDepsInfo{font-size:11.5px;color:var(--muted);}
.docDepsInfo.blocked{color:#dc2626;font-weight:600;}
.docDepsPanel{margin-top:6px;padding:8px;border:1px solid var(--line);border-radius:6px;
  background:var(--row-alt);display:flex;flex-direction:column;gap:4px;max-width:340px;}
.docDepsRow{display:flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;}
.docDepsEmpty{font-size:11.5px;color:var(--muted);}
/* Фильтры календаря документов (репорт №29) */
.docsCalFlt{font-size:12px;padding:4px 6px;border-radius:4px;border:1px solid var(--line);
  background:var(--bg);color:inherit;max-width:190px;}
/* Свёрнутые блоки «Контакты»/«История изменений» в карточке — вдвое компактнее (репорт №45):
   из ~49px высоты 34px давали padding:12px×2 + margin-bottom:10px заголовка. */
.sect.sectCollapsed{padding:4px 10px;}
.sect.sectCollapsed .ttl{margin-bottom:0;}
/* Дата создания в заголовке карточки заказа (репорт №49).
   flex:0 1 auto + min-width — поле ужимается при нехватке места (репорт bugmscx2yf0kdo1). */
.modal h2 .hdrDate{font-size:12px;padding:3px 6px;border:1px solid var(--line);border-radius:6px;
  background:var(--bg);color:inherit;font-family:inherit;flex:0 1 auto;min-width:0;max-width:100%;}
html.theme-dark .modal h2 .hdrDate{background:var(--panel);color:var(--text);}
.modal h2 .hdrDateLbl{font-size:12px;color:var(--muted);flex:0 0 auto;white-space:nowrap;}
/* Кнопка «Цвет заказа» в шапке карточки (репорт №239) + всплывающий поповер со свотчами. */
.modal h2 .hdrColorBtn{width:26px;height:26px;flex:0 0 auto;border-radius:50%;
  border:2px solid var(--line);background:var(--bg);color:inherit;cursor:pointer;padding:0;
  font-size:13px;line-height:1;display:inline-flex;align-items:center;justify-content:center;
  overflow:hidden;}
.modal h2 .hdrColorBtn:hover{border-color:var(--accent);}
html.theme-dark .modal h2 .hdrColorBtn{background:var(--panel);}
.hdrColorPop{position:absolute;z-index:1500;background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:10px;box-shadow:0 8px 24px rgba(0,0,0,.18);
  display:flex;gap:8px;flex-wrap:wrap;max-width:220px;}
html.theme-dark .hdrColorPop{background:var(--panel);}
/* ===== Кастомный DatePicker (замена native <input type="date">) — Grep "DATE PICKER" в kenguru.js.
   .weekend/.holiday — те же цвета, что у #calGrid (см. правила выше), попап — паттерн .hdrColorPop.
   Репорт №524 (2026-08-20): .dpBtn — теперь настоящий текстовый <input> (было: кнопка-ярлык +
   отдельная строка ручного ввода .dpManualInput внутри попапа — убрана целиком). */
.dpWrap{display:inline-block;position:relative;max-width:100%;}
.dpBtn{font:inherit;font-size:13px;padding:5px 9px;border:1px solid var(--line);border-radius:6px;
  background:var(--panel);color:var(--text);cursor:text;text-align:left;min-width:118px;max-width:100%;
  box-sizing:border-box;font-variant-numeric:tabular-nums;}
.dpBtn::placeholder{color:var(--muted);}
.dpBtn:hover{border-color:var(--accent);}
.dpBtn:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.dpBtn.dpManualBad{border-color:#dc2626;}
html.theme-dark .dpBtn.dpManualBad{border-color:#f87171;}
.dpWrap.dpDisabled .dpBtn{opacity:.55;cursor:not-allowed;}
.dpWrap.dpRequiredEmpty .dpBtn{border-color:#dc2626;}
.dpPop{position:absolute;z-index:1500;background:#fff;border:1px solid var(--line);
  border-radius:8px;padding:8px;box-shadow:0 8px 24px rgba(0,0,0,.18);width:236px;user-select:none;}
html.theme-dark .dpPop{background:var(--panel);}
.dpPop.dpMobile{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:min(320px,92vw);}
.dpPopHead{display:flex;align-items:center;gap:2px;margin-bottom:6px;}
.dpPopTitle{flex:1;text-align:center;font-weight:700;font-size:12.5px;text-transform:capitalize;}
.dpNav{font:inherit;font-size:13px;padding:3px 7px;border:1px solid transparent;border-radius:5px;
  background:transparent;color:var(--text);cursor:pointer;line-height:1;}
.dpNav:hover{background:var(--line2);border-color:var(--line);}
.dpPopDow{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;margin-bottom:2px;}
.dpPopDow span{text-align:center;font-size:10.5px;color:var(--muted);font-weight:600;padding:2px 0;}
.dpPopGrid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;}
.dpDay{font:inherit;font-size:12.5px;padding:6px 0;border:1px solid transparent;border-radius:5px;
  background:#fff;color:var(--text);cursor:pointer;text-align:center;font-variant-numeric:tabular-nums;position:relative;}
html.theme-dark .dpDay{background:var(--panel);}
.dpDay:hover{background:#eff6ff;}
html.theme-dark .dpDay:hover{background:#233047;}
.dpDay.outside{color:var(--muted);opacity:.5;}
.dpDay.weekend{background:#fef2f2;}
html.theme-dark .dpDay.weekend{background:#241c20;}
.dpDay.holiday{background:#fee2e2;font-weight:700;color:#7f1d1d;}
html.theme-dark .dpDay.holiday{background:#2e1b1b;color:#fca5a5;}
.dpDay.holiday.weekend{background:#fecaca;}
html.theme-dark .dpDay.holiday.weekend{background:#341d1d;}
.dpDay.holiday:hover::after{
  content:attr(data-hol);position:absolute;left:50%;bottom:calc(100% + 4px);transform:translateX(-50%);
  background:#7f1d1d;color:#fff;font-size:10.5px;font-weight:600;padding:3px 7px;border-radius:4px;
  white-space:nowrap;z-index:5;pointer-events:none;}
.dpDay.today{box-shadow:inset 0 0 0 2px var(--accent);}
.dpDay.sel{background:var(--accent) !important;color:#fff !important;font-weight:700;}
.dpDay.disabled{opacity:.3;cursor:not-allowed;}
.dpDay:focus-visible{outline:2px solid var(--accent-d);outline-offset:-2px;}
.dpPopFoot{display:flex;gap:6px;margin-top:6px;padding-top:6px;border-top:1px solid var(--line2);}
.dpFootBtn{flex:1;font:inherit;font-size:11.5px;padding:5px 0;border:1px solid var(--line);border-radius:5px;
  background:var(--panel);color:var(--text);cursor:pointer;}
.dpFootBtn:hover{border-color:var(--accent);color:var(--accent-d);}
/* Правая мини-панель документооборота (репорт №56): третий flex-ребёнок #layout,
   зеркало сайдбара #dash. Только Kenguru (класс kenOnly). Вкладка #ptoOvl её НЕ
   накрывает (right = ширине панели, правило у блока «Задачи ПТО» выше — при смене
   width ниже менять и там); #calOvl/#docsCalOvl (right:0) накрывают — это ок. */
#docsMini{flex:0 0 auto;width:clamp(234px,18.2vw,325px);padding:12px;background:var(--panel); /* №292: +30% к прежним 180/14vw/250 */
  border-left:1px solid var(--line);display:flex;flex-direction:column;gap:8px;overflow-y:auto;}
#docsMini .calNavBtn{width:100%;padding:9px 8px;border:1px solid var(--line);background:var(--panel);
  border-radius:var(--radius-pill);cursor:pointer;font-size:13px;font-weight:500;color:var(--muted);white-space:nowrap;}
#docsMini .calNavBtn:hover{border-color:transparent;background:var(--hover);}
#docsMiniToggleBtn{display:none;}
#docsMini .dmCap{font-size:11px;color:var(--muted);font-weight:700;text-transform:uppercase;letter-spacing:.4px;margin-top:4px;}
/* Чипы-фильтры по типам документов (репорт bugmsd66902jzhu) */
.dmTypeBar{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:2px;}
.dmTypeChip{font-size:10px;padding:3px 7px;border:1px solid var(--line);border-radius:var(--radius-pill);
  background:var(--bg);cursor:pointer;color:var(--muted);line-height:1.2;}
.dmTypeChip:hover{background:var(--hover);}
.dmTypeChip.active{background:var(--accent-tint);color:var(--accent-d);border-color:transparent;font-weight:600;}
#docsMini .dmCap.overdue{color:#dc2626;}
.dmRow{border:1px solid var(--line);border-radius:6px;padding:5px 8px;font-size:13px;cursor:pointer;background:var(--bg);} /* №298: было 11px */
.dmRow:hover{background:var(--hover);}
.dmRow .dmDate{font-weight:700;}
.dmRow.overdue{border-color:#dc2626;background:#fef2f2;}
.dmRow.closed{border-color:#bfe4c8;background:#eefdf3;}
.dmRow .dmSub{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#docsMini .dmEmpty{font-size:11px;color:var(--muted);}
.dmGroup{display:flex;flex-direction:column;gap:4px;}
/* №294: визуальный отступ группы «Заявки СО (ДКР)» от заказов KENGURU выше по списку */
.dmSvcGroup{margin-top:12px;padding-top:10px;border-top:1px solid var(--line);}
.dmGroupHd{display:flex;align-items:center;gap:5px;padding:5px 6px;border-radius:6px;cursor:pointer;
  font-size:11px;font-weight:600;background:var(--bg);border:1px solid var(--line);}
.dmGroupHd:hover{background:var(--hover);}
.dmGroupHd.overdue{border-color:#dc2626;}
.dmGroupArr{color:var(--muted);flex:0 0 auto;}
.dmGroupTtl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.dmBadge{flex:0 0 auto;background:var(--accent-tint);color:var(--accent-d);border-radius:9px;
  padding:1px 6px;font-size:10px;}
.dmBadge.overdue{background:#fee2e2;color:#dc2626;}
.dmGroupBody{display:flex;flex-direction:column;gap:4px;padding-left:10px;}
.dmZGroup{display:flex;flex-direction:column;gap:4px;}
.dmZGroupHd{display:flex;align-items:center;gap:5px;padding:6px 7px;border-radius:6px;cursor:pointer;
  font-size:11px;font-weight:700;background:var(--panel);border:1px solid var(--line);}
.dmZGroupHd:hover{background:var(--hover);}
.dmZGroupHd.overdue{border-color:#dc2626;}
.dmZGroupTtl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:uppercase;letter-spacing:.3px;}
.dmZGroupBody{display:flex;flex-direction:column;gap:6px;padding-left:8px;border-left:2px solid var(--line);margin-top:2px;}
html.theme-dark .dmRow.overdue{background:#3a1414;}
html.theme-dark .dmRow.closed{background:#0f2e1c;}
html.theme-dark .dmBadge.overdue{background:#3a1414;color:#f87171;}
/* Репорты №423/№445: верхнеуровневые разделы панели «Документы» — «Заказы» /
   «Сервисное обслуживание» / «Замечания по документации» */
.dmSection{display:flex;flex-direction:column;gap:5px;}
.dmSection+.dmSection{margin-top:10px;padding-top:9px;border-top:1px solid var(--line);}
.dmSecHd{display:flex;align-items:center;gap:6px;padding:7px 8px;border-radius:7px;cursor:pointer;
  font-size:12px;font-weight:700;background:var(--accent-tint);border:1px solid var(--line);}
.dmSecHd:hover{background:var(--hover);}
.dmSecTtl{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-transform:uppercase;letter-spacing:.35px;}
.dmSecBody{display:flex;flex-direction:column;gap:5px;padding-left:4px;}
/* Репорт №447: чип фокуса на комплексе в журнале замечаний */
.mkCxFocusChip{display:inline-flex;align-items:center;gap:5px;padding:4px 8px;border:1px solid var(--accent,#2563eb);
  border-radius:14px;font-size:12px;background:var(--accent-tint);color:var(--text);white-space:nowrap;}
.mkCxFocusChip .mkCxFocusX{cursor:pointer;font-weight:700;padding:0 2px;color:var(--muted);}
.mkCxFocusChip .mkCxFocusX:hover{color:#dc2626;}
@media(max-width:900px){#docsMini{display:none;}}
@media(max-width:600px){
  #dash{order:0;}
  #docsMini{order:1;}
  #mainCol{order:2;}
  #docsMini{display:flex;width:100%;box-sizing:border-box;position:static;max-height:none;min-height:0;
    border-left:0;border-top:1px solid var(--line);overflow:visible;}
  #docsMiniToggleBtn{display:block;width:100%;text-align:left;}
  #docsMini:not(.dmMobileOpen) #docsMiniList,
  #docsMini:not(.dmMobileOpen) #docsMiniOpenBtn{display:none;}
}

/* ==================== БЛОКИРОВКИ ЗАКАЗОВ (Этап 2, серверный режим) ====================
   Классы навешиваются только из клиентского sync-блока (Учёт_заказов.html) — вне серверного
   режима никогда не применяются. .lockBanner переиспользует токены --lswarn-bg/--lswarn-fg
   (см. секцию «АУДИТ ТЁМНОЙ ТЕМЫ» выше) — тот же идиом, что и предупреждение о localStorage. */
/* Репорт №637: раньше pointer-events:none стояло на ВСЁМ #mBody — текст был виден, но
   ничего не кликалось вообще (даже фото/схемы/паспорта в просмотрщике, спецификация
   комплекса, свёрнутые блоки «Контакты»/«История»). Теперь блокируем ТОЛЬКО реальные
   элементы ввода/действия (по тегу — не по классу, чтобы не зависеть от того, что
   именно навешено на конкретную кнопку) — read-only-вьюер может кликать по всему
   остальному (карточку комплекса открыть, фото/PDF посмотреть, секцию развернуть,
   текст выделить и скопировать — user-select больше не блокируется). ЕДИНСТВЕННОЕ
   известное исключение — кнопка «Показать все спецификации» (#cxSpecAllBtn, реальный
   <button>, но чисто просмотровая) — помечена .lockViewSafe и явно разблокирована.
   Namespace-по-тегу — сознательный safe-by-default: если где-то в карточке появится
   НОВАЯ мутирующая кнопка/поле, она унаследует blocking автоматически (в отличие от
   allowlist по классу, где забытый .lockViewSafe означал бы «не показывать», а не
   «нельзя отредактировать»).
   ⚠️ Живым прогоном найдены и закрыты 2 обхода блокировки по тегу (оба — нативное
   поведение браузера, не «клик по заблокированному элементу», поэтому pointer-events
   на самом input/button их не ловит): (1) чекбоксы услуг обёрнуты в <label> — клик по
   САМОЙ label (текст рядом, не по input) активирует связанный чекбокс средствами
   браузера в обход pointer-events на input; блокируем и такие label через :has();
   (2) ручки перетаскивания порядка позиций/документов (.cxGrip/.docGrip) — обычные
   <span draggable=true>, не входят ни в один из заблокированных тегов — перетаскивание
   меняло бы порядок draft.complexes[]/order.docs[] в режиме «только просмотр». */
#ovl.lockedReadOnly #mBody{opacity:.72;}
#ovl.lockedReadOnly #mBody input:not(.lockViewSafe),
#ovl.lockedReadOnly #mBody select:not(.lockViewSafe),
#ovl.lockedReadOnly #mBody textarea:not(.lockViewSafe),
#ovl.lockedReadOnly #mBody button:not(.lockViewSafe),
#ovl.lockedReadOnly #mBody [contenteditable]:not(.lockViewSafe),
#ovl.lockedReadOnly #mBody label:has(input,select,textarea):not(.lockViewSafe),
#ovl.lockedReadOnly #mBody .cxGrip,
#ovl.lockedReadOnly #mBody .docGrip{pointer-events:none;}
#ovl.lockedReadOnly #mSave,#ovl.lockedReadOnly #mDelete{display:none;}
.lockBanner{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:14px;padding:10px 14px;
  border-radius:8px;background:var(--lswarn-bg,rgba(220,53,69,.09));color:var(--lswarn-fg,#b02a37);
  font-size:13px;font-weight:600;pointer-events:auto;}
.lockBanner .btn{pointer-events:auto;}
/* строка-иконка занятости в главной таблице (buildRow, kenguru.js) */
.rowLocked{color:#dc2626;}
html.theme-dark .rowLocked{color:#f87171;}
/* репорт №644: замочек справа от номера — виден сразу, без наведения на ячейку */
.rowLockedIcon{margin-left:2px;font-size:.9em;}

/* ==================== ОБРЫВ СВЯЗИ (Этап 3) ==================== */
#connLostBanner{position:fixed;left:0;right:0;top:0;z-index:400;display:none;align-items:center;
  justify-content:center;gap:10px;padding:8px 14px;background:#dc2626;color:#fff;font-size:13px;
  font-weight:700;box-shadow:0 2px 8px rgba(0,0,0,.35);}
#connLostBanner.show{display:flex;}
body.connLost #ovl #mBody{pointer-events:none;opacity:.72;user-select:none;}
body.connLost #ovl #mSave,body.connLost #ovl #mDelete{display:none;}

/* ==================== ТЕХ. РАБОТЫ (пауза сервера — только просмотр) ==================== */
#maintBanner{position:fixed;left:0;right:0;top:0;z-index:399;display:none;align-items:center;
  justify-content:center;gap:10px;padding:8px 14px;background:#d97706;color:#fff;font-size:13px;
  font-weight:700;box-shadow:0 2px 8px rgba(0,0,0,.35);}
#maintBanner.show{display:flex;}
body.maintMode #ovl #mBody{pointer-events:none;opacity:.72;user-select:none;}
body.maintMode #ovl #mSave,body.maintMode #ovl #mDelete{display:none;}
/* ⚠ АУДИТ 2026-09-02, major. Запрет на время «Тех. работ» / обрыва связи стоял
   ТОЛЬКО на теле карточки заказа. Календарь (меню ячейки меняет даты и услуги),
   массовые операции, реестр СО, приёмки и задачи ПТО оставались полностью
   рабочими: правка ложилась в память и localStorage, на сервер не уходила, а по
   окончании работ перезагрузка состояния с сервера её молча стирала. */
/* ⚠ ДОРАБОТКА (ревью собственных правок, тот же день). Первая версия гасила
   pointer-events у КОНТЕЙНЕРОВ целиком — и вместе с правками отключала просмотр:
   колесо мыши над таблицей не прокручивало её, кнопки «✕ Закрыть» в футерах не
   работали (исключение было только для крестика в заголовке), а в файловом режиме
   «только просмотр» это висело постоянно. Блокируем не контейнер, а сами органы
   ввода — по ТЕГУ, как это давно сделано для занятой карточки заказа (репорт №637):
   заново появившийся input/button унаследует запрет автоматически. Прокрутка,
   выделение текста, открытие документов и закрытие окон остаются доступны. */
body.maintMode :is(#calGrid,#bulkBar,#svcRegOvl .modal,#svcEditOvl .modal,#priemkiOvl .modal,#ptoOvl,#ptoCardOvl .modal) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input),label:has(select),label:has(textarea)),
body.connLost :is(#calGrid,#bulkBar,#svcRegOvl .modal,#svcEditOvl .modal,#priemkiOvl .modal,#ptoOvl,#ptoCardOvl .modal) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input),label:has(select),label:has(textarea)){
  pointer-events:none!important;opacity:.6;}
/* клик по ячейке календаря открывает меню правки дат/услуг — гасим сами ячейки,
   но НЕ сетку: колесо мыши над «мёртвой» ячейкой уходит контейнеру, и он прокручивается */
body.maintMode #calGrid td,body.connLost #calGrid td{pointer-events:none;}
/* закрыть окно и уйти можно всегда: крестик, любые кнопки закрытия, явно
   помеченные просмотровые элементы */
body.maintMode :is(.modal h2 .x,button[id*="lose"],.lockViewSafe),
body.connLost :is(.modal h2 .x,button[id*="lose"],.lockViewSafe){pointer-events:auto!important;opacity:1;}

/* ⚠ АУДИТ 2026-09-02 (ревью собственных правок). Файловый режим «только просмотр»
   сперва переиспользовал body.maintMode — а вместе с ним прилетало правило
   `body.maintMode #ovl #mBody{pointer-events:none}` из режима обрыва связи, и
   карточку заказа нельзя было ни прокрутить, ни открыть из неё фото. Для просмотра
   снимка нужен СВОЙ класс: правки запрещены, ЧТЕНИЕ — нет. */
body.fileRO :is(#calGrid,#bulkBar,#svcRegOvl .modal,#svcEditOvl .modal,#priemkiOvl .modal,#ptoOvl,#ptoCardOvl .modal,#ovl #mBody) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input),label:has(select),label:has(textarea)){
  pointer-events:none!important;opacity:.6;}
body.fileRO #calGrid td{pointer-events:none;}
body.fileRO #ovl #mSave,body.fileRO #ovl #mDelete{display:none!important;}
body.fileRO :is(.modal h2 .x,button[id*="lose"],.lockViewSafe){pointer-events:auto!important;opacity:1;}

/* ==================== «ЗАДАЧИ ПТО» (наряд-задачи, экран-режим) ==================== */
#ptoSummary{margin-bottom:8px;flex:0 0 auto;}
.ptoSumHead{display:flex;align-items:center;gap:12px;margin-bottom:6px;flex-wrap:wrap;cursor:pointer;user-select:none;}
.ptoSumArr{display:inline-block;width:12px;color:var(--muted);}
.ptoMonthSw{display:inline-flex;align-items:center;gap:6px;}
#ptoMonthLbl{font-weight:600;min-width:130px;text-align:center;}
table.ptoSumTbl{border-collapse:collapse;font-size:12px;min-width:420px;}
table.ptoSumTbl th,table.ptoSumTbl td{border:1px solid var(--line);padding:3px 10px;text-align:left;}
table.ptoSumTbl th{background:var(--hover);font-weight:600;}
table.ptoSumTbl tr.ptoSumTot td{font-weight:700;background:var(--accent-tint);}
#ptoToolbar{display:flex;align-items:center;gap:8px;margin-bottom:6px;flex-wrap:wrap;flex:0 0 auto;}
#ptoChipBar{display:flex;flex-wrap:wrap;gap:4px;}
.ptoChip{font-size:11px;padding:3px 9px;border:1px solid var(--line);border-radius:var(--radius-pill);
  background:transparent;cursor:pointer;color:inherit;}
.ptoChip:hover{background:var(--hover);}
.ptoChip.active{background:var(--accent-tint);color:var(--accent-d);border-color:transparent;font-weight:600;}
/* wrapInputWithClear оборачивает input в .searchInputWrap — флекс-итемом тулбара
   становится ОБЁРТКА, поэтому растягиваем её (ревью; ср. компенсации .catbar/#toolbar) */
#ptoToolbar > .searchInputWrap{flex:1 1 220px;min-width:160px;}
#ptoSearch{flex:1 1 220px;min-width:160px;}
#ptoTbl{width:100%;border-collapse:collapse;font-size:12px;}
#ptoTbl th,#ptoTbl td{border-bottom:1px solid var(--line);padding:6px 8px;text-align:left;vertical-align:top;}
#ptoTbl thead th{position:sticky;top:0;background:var(--bg);z-index:2;}
#ptoTbl tbody tr{cursor:pointer;}
#ptoTbl tbody tr:hover{background:var(--hover);}
tr.ptoOverdue td{background:rgba(220,38,38,.08);}
tr.ptoSoon td{background:rgba(217,119,6,.10);}
/* Репорт №705: заголовки-секции таблицы задач (Новая / В работе / Выполнено),
   кликабельны — сворачивают секцию. Селектор ОБЯЗАН нести #ptoTbl (не просто
   tr.ptoSecRow td) — иначе проигрывает по специфичности общему `#ptoTbl th,
   #ptoTbl td{padding:6px 8px}` (ID > class), несмотря на более позднее место
   в файле: найдено живым прогоном #721 — padding-top визуально оставался 6px
   вместо заданных здесь 10px, пока селектор не получил тот же вес ID. */
#ptoTbl tr.ptoSecRow td{background:var(--th-bg,rgba(148,163,184,.14));font-weight:700;font-size:12px;
  padding:10px 10px 5px;cursor:pointer;user-select:none;border-top:1px solid var(--border);}
#ptoTbl tr.ptoSecRow:hover td{background:rgba(148,163,184,.24);}
tr.ptoSecRow .ptoSecArr{display:inline-block;width:12px;color:var(--muted);}
tr.ptoSecRow .ptoSecCnt{color:var(--muted);font-weight:600;}
.ptoCellDesc{color:var(--muted);font-size:11px;margin-top:2px;}
.ptoSt{display:inline-block;font-size:11px;padding:1px 8px;border-radius:var(--radius-pill);font-weight:600;white-space:nowrap;}
.ptoSt-new{background:rgba(59,130,246,.12);color:#1d4ed8;}
.ptoSt-work{background:rgba(217,119,6,.14);color:#b45309;}
.ptoSt-done{background:rgba(22,163,74,.14);color:#15803d;}
html.theme-dark .ptoSt-new{color:#93c5fd;}
html.theme-dark .ptoSt-work{color:#fcd34d;}
html.theme-dark .ptoSt-done{color:#86efac;}
.ptoOrdLink{color:var(--accent-d);text-decoration:underline;cursor:pointer;}
html.theme-dark .ptoOrdLink{color:#93c5fd;}
/* карточка задачи */
.ptoFld{margin-bottom:8px;}
.ptoFld>label{display:block;font-size:11px;color:var(--muted);margin-bottom:3px;}
.ptoFld input[type=text],.ptoFld textarea,.ptoFld select{width:100%;box-sizing:border-box;}
#ptoCardFDesc{width:100%;min-width:0;max-width:100%;resize:none;overflow-y:hidden;}
#ptoCardFOrdDir,#ptoCardFOrdYear,#ptoCardFOrdNum{width:auto;}
.ptoFldRow{display:flex;gap:10px;flex-wrap:wrap;}
.ptoFldRow>.ptoFld{flex:1 1 140px;min-width:120px;}
#ptoStatusSeg{display:inline-flex;gap:4px;flex-wrap:wrap;}
#ptoShotsList{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:6px;}
.ptoShotItem{position:relative;}
.ptoShotItem img{width:96px;height:64px;object-fit:cover;border:1px solid var(--line);border-radius:4px;cursor:pointer;display:block;}
.ptoShotDel{position:absolute;top:-6px;right:-6px;width:18px;height:18px;line-height:15px;border-radius:50%;
  border:1px solid var(--line);background:var(--bg);cursor:pointer;font-size:11px;padding:0;color:#dc2626;}
#ptoShotAddBox{border:1px dashed var(--line);border-radius:6px;padding:8px;text-align:center;color:var(--muted);font-size:11px;}
#ptoCommentsList{display:flex;flex-direction:column;gap:6px;max-height:220px;overflow:auto;}
.ptoComment{border:1px solid var(--line);border-radius:6px;padding:5px 8px;}
.ptoCommentHead{font-size:10px;color:var(--muted);margin-bottom:2px;}
.ptoCommentText{font-size:12px;white-space:pre-wrap;overflow-wrap:anywhere;}
@media(max-width:600px){
  table.ptoSumTbl{min-width:0;width:100%;}
  #ptoTbl th,#ptoTbl td{padding:5px 5px;}
  /* Репорт от 18.09.2026: на телефоне таблица задач — только «Название» (растянуто на
     максимум) и «Срок» (узко); № п/п, Создана, Норматив, Статус, Выполнена, Заказ —
     скрыты (остаются доступны в карточке задачи по клику на строку). Позиции колонок
     см. Учёт_заказов.html #ptoHeadRow: 1=№, 2=Название, 3=Создана, 4=Срок, 5=Норматив,
     6=Статус, 7=Выполнена, 8=Заказ. */
  #ptoTbl th:nth-child(1),#ptoTbl td:nth-child(1),
  #ptoTbl th:nth-child(3),#ptoTbl td:nth-child(3),
  #ptoTbl th:nth-child(5),#ptoTbl td:nth-child(5),
  #ptoTbl th:nth-child(6),#ptoTbl td:nth-child(6),
  #ptoTbl th:nth-child(7),#ptoTbl td:nth-child(7),
  #ptoTbl th:nth-child(8),#ptoTbl td:nth-child(8){display:none;}
  #ptoTbl th:nth-child(2),#ptoTbl td:nth-child(2){width:auto;}
  #ptoTbl th:nth-child(4),#ptoTbl td:nth-child(4){width:60px;white-space:nowrap;padding-left:4px;padding-right:4px;}
}

/* ===== Репорты №773/№775 (2026-09-02): общий список файлов «как в Windows» =====
   Один вид у ВСЕХ мест со свободным деревом /api/fsbrowse (общая точка — _fsRenderInto
   в Учёт_заказов.html): свободный браузер #fsBrowserList, «Загрузка документации»
   #docUploadList, «Систематизация документов» #docSysAssignList и докед-панель папки
   заказа/заявки #orderFolderList.
   Строка и шапка — НЕЗАВИСИМЫЕ CSS-grid с одинаковым grid-template-columns (--fsl-cols),
   поэтому колонки выравниваются, а сам контейнер остаётся обычным блоком: «⬆ .. (вверх)»,
   «Папка пуста.» и кнопка «📥 Подгрузить паспорта» (репорт №641) ложатся отдельными
   блоками во всю ширину, как раньше. */
/* Ревью: последний трек (ячейка действий) обязан быть ФИКСИРОВАННЫМ — шапка и строки это
   ДВА независимых грида, и трек auto в них считается по своему содержимому: в шапке ячейка
   действий пустая (0px), в строке — кнопки ⬇/🗑 (~52px), из-за чего колонки разъезжались. */
.fsList{--fsl-cols:minmax(0,1fr) 104px 52px 74px 56px;}
/* пикеры папки (dirsOnly): файлов там нет вовсе — «Тип»/«Размер» лишние */
.fsList.fsDirsOnly{--fsl-cols:minmax(0,1fr) 104px 0px;}   /* в пикерах папки кнопок действий нет */
.fsList.fsDirsOnly .fsCellType,.fsList.fsDirsOnly .fsCellSize{display:none;}
.fsRow{display:grid;grid-template-columns:var(--fsl-cols);align-items:center;gap:8px;
  padding:5px 8px;border-radius:6px;}
.fsRow.fsRowDir{cursor:pointer;}
.fsRow:not(.fsHead):hover{background:var(--hover);}
.fsCellName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.fsCellDate,.fsCellSize,.fsCellType{font-size:11px;color:var(--muted);white-space:nowrap;}
.fsCellSize{text-align:right;}
.fsCellType{min-width:0;overflow:hidden;}
/* репорт №775: имя файла — сама ссылка «открыть» */
.fsName{color:var(--text);text-decoration:none;}
.fsName:hover{text-decoration:underline;}
/* репорт №677: короткая текстовая метка формата вместо эмодзи-иконки — переехала в колонку «Тип» */
.fsExt{display:inline-block;min-width:34px;text-align:center;padding:2px 5px;border-radius:5px;
  border:1px solid var(--line);background:var(--hover);color:var(--muted);font-size:10px;
  font-weight:700;letter-spacing:.02em;line-height:1.4;}
.fsActs{display:flex;align-items:center;justify-content:flex-end;gap:4px;min-width:0;}
/* ===== Репорт №791 — множественный выбор в списке файлов =====
   Подсветка выбранной строки перебивает :hover (иначе под курсором выбор «пропадает»).
   Панель действий — обычный блок во всю ширину контейнера, как «⬆ .. (вверх)» и
   «Папка пуста.»: контейнер списка НЕ грид, гридом являются сами строки. */
.fsRow.fsRowSel,.fsRow.fsRowSel:hover{background:var(--accent);color:#fff;}
.fsRow.fsRowSel .fsCellDate,.fsRow.fsRowSel .fsCellSize,.fsRow.fsRowSel .fsCellType,
.fsRow.fsRowSel .fsName,.fsRow.fsRowSel .fsIconBtn{color:#fff;}
.fsRow.fsRowSel .fsExt{border-color:rgba(255,255,255,.5);background:rgba(255,255,255,.15);color:#fff;}
/* Панель стоит ПОСЛЕ строк и прилипает к низу прокручиваемой области: её появление не
   сдвигает уже показанные строки (иначе второй Ctrl+клик попадал бы по соседнему файлу). */
.fsSelBar{display:flex;align-items:center;flex-wrap:wrap;gap:6px;margin:6px 0 2px;padding:5px 8px;
  border:1px solid var(--accent);border-radius:6px;background:var(--panel);
  position:sticky;bottom:0;z-index:2;box-shadow:0 -2px 8px rgba(0,0,0,.08);}
.fsSelBar.fsSelBusy{opacity:.6;pointer-events:none;}
.fsSelCount{font-size:12px;font-weight:700;margin-right:2px;}
/* репорт №775: «Скачать» свёрнута в иконку */
.fsIconBtn{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;
  border:1px solid transparent;border-radius:6px;text-decoration:none;font-size:13px;line-height:1;
  color:var(--muted);opacity:.6;cursor:pointer;}
.fsIconBtn:hover{opacity:1;border-color:var(--line);background:var(--hover);color:var(--text);}
/* шапка-сортировка (репорт №773) */
.fsRow.fsHead{border-radius:0;border-bottom:1px solid var(--line);padding-bottom:4px;margin-bottom:2px;}
.fsHeadCell{background:none;border:none;margin:0;padding:0;font:inherit;font-size:11px;font-weight:700;
  color:var(--muted);text-transform:uppercase;letter-spacing:.02em;text-align:left;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.fsHeadCell:hover{color:var(--text);}
.fsHeadCell.fsCellSize{text-align:right;}
/* шапка липнет к верху ТОЛЬКО там, где прокручивается сам контейнер списка (инлайновый
   overflow:auto + padding:4px в разметке этих трёх окон); в докед-панели прокручивается
   .ofpBody, а не .ofpList — там sticky не нужен. */
#fsBrowserList .fsHead,#docUploadList .fsHead,#docSysAssignList .fsHead{
  position:sticky;top:-4px;z-index:1;background:var(--panel);
  margin:-4px -4px 2px;padding:8px 12px 4px;}
/* Докед-панель узкая (480px, на ≤1240px — 92vw). Ревью репорта №773: при четырёх
   колонках имени остаётся ~140px и оно режется на «Акт осмотра МАФ Физк…» — ровно то,
   на что и был репорт. Поэтому в панели колонку «Тип» скрываем (расширение и так видно
   в самом имени файла), а имени отдаём освободившееся место. */
#orderFolderPanel .fsList{--fsl-cols:minmax(0,1fr) 92px 62px 56px;font-size:12px;}
#orderFolderPanel .fsCellType{display:none;}
@media(max-width:600px){
  .fsList,#orderFolderPanel .fsList{--fsl-cols:minmax(0,1fr) 92px 56px;}
  .fsList .fsCellType,.fsList .fsCellSize{display:none;}
}

/* Репорт №835 (2026-09-17): правка наименования и артикула позиции ДЛЯ АКТА в окне
   «КС-2/КС-3». Карандаш проявляется при наведении на строку позиции (и всегда виден
   с клавиатуры — :focus-visible), метка «✎ для акта» показывает, что значения в акте
   отличаются от заказа. */
.ks2PosEdit{opacity:0;cursor:pointer;margin-left:4px;color:var(--muted);transition:opacity .12s;}
.ks2PosRow:hover .ks2PosEdit,.ks2PosEdit:focus-visible{opacity:1;}
.ks2PosEdit:hover{color:var(--fg,inherit);}
.ks2PosMark{font-size:11px;color:var(--muted);border:1px solid var(--line);border-radius:5px;padding:0 4px;margin-left:4px;white-space:nowrap;}

/* Репорт №818 (2026-09-17): плашка формата СЛЕВА от имени файла — только там, где колонка
   «Тип» скрыта: докед-панель «Папка заказа/заявки» и узкий экран. В полноразмерных окнах
   (обзор файлов, загрузка документации) колонка «Тип» на месте, плашка в имени не нужна. */
.fsExtInline{display:none;margin-right:6px;flex:0 0 auto;vertical-align:1px;}
#orderFolderPanel .fsCellName .fsExtInline{display:inline-block;}
#orderFolderPanel .fsCellName{display:flex;align-items:center;min-width:0;}
#orderFolderPanel .fsCellName .fsName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
@media(max-width:600px){
  .fsList .fsCellName .fsExtInline{display:inline-block;}
  .fsList .fsCellName{display:flex;align-items:center;min-width:0;}
  .fsList .fsCellName .fsName{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
}

/* ===================================================================
   РЕПОРТЫ 2026-09-19 (№885–№918): мобильная шапка/дашборд, «Панель управления» разделами,
   таблицы без горизонтальной прокрутки, «Сервисное обслуживание»/«Задачи ПТО»/«Календарь» как режимы.
   =================================================================== */
/* №910: «Панель управления» — три раздела-кнопки сверху (вид как у переключателей вида в окнах схем/чертежей) */
.syncTabs{display:flex;gap:8px;margin:4px 0 12px;}
.syncTabs .cxRefKindBtn{flex:1 1 0;min-width:0;white-space:normal;line-height:1.2;padding:8px 6px;text-align:center;}
.syncPane .syncStep:first-child{margin-top:0;}
/* №900/№904: кнопка «Комплексы» для строки дашборда — только на телефоне */
.mobOnly{display:none;}
@media(max-width:600px){
  /* №906: шапка на телефоне — ОДНА строка (≈ вдвое ниже): ☰ · АСУ ПТО · имя · иконки ⚙ ◐ ⎋ */
  header{padding:3px 8px;gap:6px;flex-wrap:nowrap;}
  header h1{font-size:12.5px;white-space:nowrap;flex:0 0 auto;margin:0;}
  .navMenuBtn{padding:2px 8px;line-height:1.2;flex:0 0 auto;}
  #syncBadge{flex:1 1 auto;min-width:0;margin-left:0;flex-wrap:nowrap;justify-content:flex-end;row-gap:0;gap:5px;}
  #authUserBadge{flex:1 1 auto;min-width:0;margin-left:0;flex-wrap:nowrap;justify-content:flex-end;gap:4px;}
  #authUserBadge #authUserName{flex:0 1 auto;max-width:none;min-width:0;font-size:11.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right;}
  #syncBtn,#themeBtn,#authLogoutBtn{font-size:0!important;width:30px;height:30px;min-width:30px;padding:0!important;
    align-items:center;justify-content:center;flex:0 0 auto;}
  #syncBtn{display:inline-flex;}
  #themeBtn,#authLogoutBtn{display:inline-flex;}
  #syncBtn::before{content:"⚙";font-size:16px;line-height:1;}
  #themeBtn::before{content:"◐";font-size:16px;line-height:1;}
  #authLogoutBtn::before{content:"⎋";font-size:16px;line-height:1;}
  #authLogoutWrap{flex:0 0 auto;}
  /* №900: на телефоне скрыты «Создать расстановку», «Новый заказ», «Открыть таблицу», «Сводка по комплексам» */
  #plStandaloneBtn,#addBtn,#gsSyncOpen,#cxSumBtn{display:none!important;}
  /* №902: «История» и «Корзина» скрыты */
  #trashBtn,#histBtn{display:none!important;}
  /* №904: «Комплексы» — в строку кнопок с «Репорты» (кнопка тулбара скрыта, её дубль живёт в #dashTools) */
  #cxRefBtn{display:none!important;}
  #dashTools .mobOnly{display:inline-block;}
  /* №898: «Недавние» — только 3 позиции */
  #recentList .recentItem:nth-of-type(n+4){display:none;}
  /* №908: три плитки дашборда («Все заказы» / «Паспорта не отгружены» / «Расстановка отсутствует») — в одну строку */
  #dashChips{flex-wrap:nowrap;}
  #dashChips .chip{flex:1 1 0;min-width:0;padding:6px 5px;}
  #dashChips .chip .l{font-size:11px;line-height:1.2;}
  /* №915: подсказка горячих клавиш на телефоне не нужна */
  #hotkeyHint{display:none!important;}
}

/* №885/№887 (2026-09-19): таблицы без горизонтальной прокрутки — ширина колонок подбирается по содержимому;
   артикулы, номера и числа — строго в одну строку, длинные названия переносятся по словам. */
td[style*="monospace"],table td.r:not([colspan]),table th.r,table th[style*="nowrap"]{white-space:nowrap;}
#orderSpecPanel table,#svcCxPanel table.svcCxSpecTbl{width:100%;table-layout:auto;}
#orderSpecPanel #ospPaneAggregate,#orderSpecPanel #ospPaneByComplex{overflow-x:hidden;}
@media(max-width:600px){
  #ovl .mbody table.cxtbl{min-width:0;width:100%;table-layout:auto;}
  #ovl .mbody table.cxtbl th{width:auto!important;}
  #ovl .mbody .sect{overflow-x:hidden;}
  .modal td,.modal th,#orderSpecPanel td,#orderSpecPanel th{overflow-wrap:break-word;}
  #ovl .mbody table.cxtbl td input:not([type=checkbox]):not([type=radio]),#ovl .mbody table.cxtbl td select{min-width:0;max-width:100%;box-sizing:border-box;}
  #orderSpecPanel table{min-width:0;}
}

/* №893: колонка с чекбоксами скрыта пользователем (меню «Видимые столбцы» → «Выбор (галочки)») */
body.hideSelCol th.selcell,body.hideSelCol td.selcell{display:none!important;}

/* ===== Режимы-направления (репорты №895/№917): СО, Задачи ПТО, Календарь ===== */
/* в любом режиме: плитки/«недавние»/кнопки сводки и кнопки годов ДКР прячутся — остаётся переключатель направлений */
body.in-mode #dashChips,body.in-mode #dashTools,body.in-mode #recentBox,body.in-mode #dirYearSwitch{display:none!important;}
/* «Задачи ПТО» и «Календарь» — на весь экран (панель «Документы» скрыта) */
body.mode-pto #docsMini,body.mode-cal #docsMini{display:none!important;}
@media(min-width:901px){ body.mode-pto #ptoOvl{right:0;} }
/* левая панель режима «Сервисное обслуживание»: годы СО + плитки статусов акта */
#svcDash{display:none;flex-direction:column;gap:8px;}
body.mode-svc #svcDash{display:flex;}
#svcYearSwitch{display:flex;gap:4px;flex-wrap:wrap;}
#svcYearSwitch .dirYearBtn{flex:1 1 auto;min-width:42px;padding:6px 4px;border:1px solid var(--line);background:var(--panel);border-radius:var(--radius-pill);
  cursor:pointer;font-size:12px;font-weight:500;color:var(--muted);
  transition:background .14s ease,border-color .14s ease,color .14s ease,box-shadow .14s ease;}
#svcYearSwitch .dirYearBtn:hover{border-color:transparent;background:var(--hover);}
#svcYearSwitch .dirYearBtn.active{border-color:transparent;background:var(--accent-tint);color:var(--accent-d);font-weight:600;}
html.theme-dark #svcYearSwitch .dirYearBtn{background:var(--panel-2,var(--panel));color:var(--muted);}
html.theme-dark #svcYearSwitch .dirYearBtn.active{background:var(--accent-tint);color:var(--accent-d);}
#svcChips{display:flex;flex-direction:column;gap:6px;}
/* экран СО — страница-режим (паттерн #ptoOvl): без рамки/тени/×, справа — «Документы» */
#svcRegOvl{position:fixed;top:var(--head-h,0px);left:var(--dash-w);right:0;bottom:0;
  background:var(--bg);padding:0;z-index:30;display:none;overflow:hidden;align-items:stretch;}
#svcRegOvl.show{display:flex;flex-direction:column;}
body:has(#svcRegOvl.show){overflow:hidden;}
@media(min-width:901px){ body:not(.dir-dkr) #svcRegOvl{right:clamp(234px,18.2vw,325px);} }
@media(max-width:600px){ #svcRegOvl{left:0;top:calc(var(--head-h,0px) + var(--dash-mob-h,0px));} }
#svcPage{flex:1 1 auto;min-width:0;min-height:0;display:flex;flex-direction:column;padding:12px clamp(12px,1.4vw,22px);}
#svcToolbar{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap;flex:0 0 auto;}
#svcToolbar .svcTitle{font-size:15px;font-weight:700;}
#svcToolbar #svcRegSearch{flex:1 1 220px;min-width:160px;box-sizing:border-box;padding:8px 11px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--text);font-size:13px;}
#svcRegBody{flex:1 1 auto;min-height:0;overflow:auto;}
#svcFoot{flex:0 0 auto;padding-top:7px;color:var(--muted);font-size:12px;}
#svcTbl{width:100%;border-collapse:collapse;font-size:12px;}
#svcTbl th,#svcTbl td{border-bottom:1px solid var(--line);padding:6px 8px;text-align:left;vertical-align:top;}
#svcTbl thead th{position:sticky;top:0;background:var(--bg);z-index:2;}
#svcTbl tbody tr{cursor:pointer;}
#svcTbl tbody tr:hover{background:var(--hover);}
#svcTbl tr.svcDone td{color:var(--muted);}
#svcTbl .svcNo{text-align:center;color:var(--muted);}
#svcTbl .svcCellMono{font-family:Consolas,Menlo,monospace;font-size:11.5px;}
#svcTbl td.svcCellAdr,#svcTbl td.svcCellMaf{overflow-wrap:anywhere;}
body.maintMode :is(#svcRegOvl) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input)),
body.connLost :is(#svcRegOvl) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input)),
body.fileRO :is(#svcRegOvl) :is(input,select,textarea,button,[contenteditable],[draggable="true"],label:has(input)){pointer-events:none;opacity:.55;}
@media(max-width:600px){
  #svcChips{flex-direction:row;flex-wrap:wrap;}
  #svcChips .chip{flex:1 1 30%;min-width:0;}
  #svcTbl .svcHideM{display:none;}
  #svcTbl th,#svcTbl td{padding:5px 5px;}
  #svcToolbar .svcTitle{display:none;}
}
/* №906/№917 (доводка): кнопка «Выйти» в мобильной шапке — тёмная, как соседние иконки; СО: столбцы «№/Дата/✕» на телефоне скрыты */
@media(max-width:600px){
  #authLogoutBtn{background:transparent;color:#cbd5e1;border:1px solid #475569;border-radius:6px;box-shadow:none;}
  #authLogoutBtn::before{content:"⇥";}
  #svcTbl td.svcCellAdr{min-width:80px;}
  #svcTbl td.svcCellMaf{min-width:90px;}
}
#svcTbl td.svcNowrap{white-space:nowrap;}
/* №885 (доводка, телефон): таблицы карточки заказа и спецификации целиком в ширину экрана — компактнее отступы/кегль */
@media(max-width:600px){
  #ovl .mbody table.cxtbl th,#ovl .mbody table.cxtbl td{padding:5px 3px;}
  #ovl .mbody table.cxtbl td>button[title^="Вид"]{padding:3px 4px!important;font-size:10px!important;}
  #ovl .mbody table.cxtbl .qtyWrap{width:auto;}
  #ovl .mbody table.cxtbl .qtyWrap input{width:34px;min-width:0;padding-left:0;padding-right:0;text-align:center;}
  #ovl .mbody table.cxtbl .qtyWrap button{min-width:22px;padding:0 4px;}
  #orderSpecPanel table{font-size:11.5px;}
  #orderSpecPanel table th,#orderSpecPanel table td{padding:4px 4px;}
  #orderSpecPanel table td[style*="monospace"]{font-size:11px;}
  #orderSpecPanel table th.r,#orderSpecPanel table th{white-space:normal;}
}
@media(max-width:600px){
  #ovl .mbody table.cxtbl .qtyWrap input{width:28px;}
  #ovl .mbody table.cxtbl .qtyWrap button{min-width:20px;padding:0 3px;}
  #ovl .mbody #sectCx{padding-left:8px;padding-right:8px;}
}

/* СО (доводка): колонки таблицы не схлопываются до символа (overflow-wrap:break-word не влияет на минимальную ширину) */
#svcTbl td.svcCellAdr,#svcTbl td.svcCellMaf{overflow-wrap:break-word;}
#svcTbl td.svcCellAdr{min-width:130px;}
#svcTbl td.svcCellMaf{min-width:170px;}
#svcTbl td.svcCellMono{overflow-wrap:anywhere;min-width:96px;}
#svcTbl td.svcNowrap{white-space:nowrap;}
/* №919 (2026-09-19): на телефоне в шапке окон «×» и «свернуть» уходили на следующую строку (h2 — flex-wrap, кнопки в конце) и
   шапка получалась в 2–3 ряда. Кнопки закрытия/сворачивания теперь всегда в правом верхнем углу, шапка компактнее. */
@media(max-width:600px){
  .modal h2{position:relative;padding:6px 88px 6px 12px;gap:6px;min-height:48px;box-sizing:border-box;}   /* справа — место под «свернуть»/«×» (в правом верхнем углу) */
  .modal h2 #mCopyTitle{font-size:0!important;padding:4px 8px!important;}   /* «Копировать» в карточке — значок без текста (иначе наезжает на «свернуть») */
  .modal h2 #mCopyTitle::before{content:"⧉";font-size:14px;line-height:1;}
  .modal h2 .hdrDateLbl{display:none;}
  .modal h2 .dpWrap,.modal h2 .hdrDate{flex:0 1 116px;min-width:0;}
  .modal h2 .x,.modal h2 .winMinBtn{position:absolute;top:4px;margin:0!important;}
  .modal h2 .x{right:6px;}
  .modal h2 .winMinBtn{right:48px;}
}

/* Репорт №931: СО — кнопка «✕ Сбросить»: тусклая, пока фильтров нет, яркая — когда что-то включено */
#svcToolbar #svcResetBtn{opacity:.6;}
#svcToolbar #svcResetBtn.svcResetOn{opacity:1;border-color:#ef4444;color:#dc2626;font-weight:600;}
/* Репорт №925: «Задачи ПТО» — кнопка сброса в ряду чипов; на телефоне таблица = 70% высоты экрана,
   страница листается целиком, таблица — сама по себе (шапка таблицы липкая) */
.ptoChip.ptoChipReset{border-color:#ef4444;color:#dc2626;font-weight:600;}
@media(max-width:600px){
  #ptoPage{overflow-y:auto;-webkit-overflow-scrolling:touch;}
  #ptoTblWrap{flex:0 0 auto;height:70dvh;min-height:240px;}
}
/* Репорт №923: «Панель управления → Telegram» — два подписанных блока (уведомления сайта / нейросеть-агент);
   блок скрывается сам, если его кнопка скрыта по роли/режиму */
.tgPaneBlk{margin:10px 0 12px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel);}
.tgPaneBlk:has(button[style*="none"]){display:none;}
.tgPaneCap{font-weight:700;font-size:13px;margin-bottom:2px;}
.tgPaneDesc{font-size:12px;color:var(--muted);margin-bottom:8px;line-height:1.35;}

/* Репорт №939: закреп задач ПТО — булавка в ячейке названия (видна при наведении, у закреплённых — всегда;
   на сенсорных экранах без наведения — приглушённо всегда) и строки раздела «Закреплённые задачи» */
#ptoTbl td.ptoCellTitle{position:relative;padding-right:30px;}
.ptoPinBtn{position:absolute;top:3px;right:3px;width:24px;height:24px;padding:0;border:none;background:transparent;color:var(--muted);
  cursor:pointer;border-radius:6px;opacity:0;display:inline-flex;align-items:center;justify-content:center;transition:opacity .12s,background .12s,color .12s;}
.ptoPinBtn svg{width:14px;height:14px;display:block;}
#ptoTbl tbody tr:hover .ptoPinBtn,.ptoPinBtn:focus-visible{opacity:.75;}
.ptoPinBtn:hover{opacity:1;background:var(--hover);color:var(--accent-d);}
.ptoPinBtn.on{opacity:1;color:var(--accent-d);}
.ptoPinBtn.on svg{fill:currentColor;}
@media(hover:none){ .ptoPinBtn{opacity:.55;} .ptoPinBtn.on{opacity:1;} }
.dmRow.dmPinRow{position:relative;padding-right:24px;}
.dmRow .dmPinX{position:absolute;top:3px;right:4px;border:none;background:transparent;color:var(--muted);cursor:pointer;
  font-size:12px;line-height:1;padding:3px 5px;border-radius:4px;opacity:0;}
.dmRow:hover .dmPinX{opacity:1;}
.dmRow .dmPinX:hover{color:#dc2626;background:var(--hover);}
@media(hover:none){ .dmRow .dmPinX{opacity:.6;} }
/* 2026-09-25: справочник комплексов из «Спецификация комплексов.xlsx» (каталог сервера, cxCatalogApplyTo) */
.cxCatHint{font-size:11px;line-height:1.4;color:var(--muted);background:var(--accent-tint);border-left:3px solid var(--accent);
  border-radius:4px;padding:5px 8px;margin:6px 0;}
.cxWtNone{color:var(--warn-strong,#b45309);font-style:italic;font-weight:400;white-space:nowrap;}
.ospPaspWt{padding:6px 12px;font-size:12px;text-align:right;border-top:1px solid var(--line);color:var(--text);}
@media (max-width:600px){ .cxCatHint{font-size:12px;} .ospPaspWt{text-align:left;} }
/* СО-патч 2026-09-29 (репорты №971/№972/№973/№979/№982) — начало */
/* №971/№982: отметка сортировки в шапке СО (рядом с «✕ Сбросить») */
#svcToolbar .svcSortNote{font-size:11.5px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;max-width:260px;cursor:help;}
#svcToolbar #svcRegSearch{flex-basis:160px;}   /* место под отметку — тулбар остаётся в один ряд на 1600px */
#svcToolbar .svcSortNote.svcSortCustom{color:var(--accent-d,var(--accent));font-weight:600;}
@media(max-width:600px){ #svcToolbar .svcSortNote{max-width:none;font-size:11px;} }
/* №972: форма заявки СО — «Округ | Район | Комиссия» по 1/3 ширины (свой под-ряд), «Адрес» на всю ширину */
.svcForm>.svcRow3{grid-column:1 / -1;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px 14px;min-width:0;}
.svcForm>.svcRow3>.svcFld.svcFld{grid-column:auto;}
@media(max-width:560px){ .svcForm>.svcRow3{grid-template-columns:1fr;} }
/* №973: папка заявки СО — «Похожие папки» и отметка ручной привязки */
#orderFolderPanel .ofpSvcLinkTtl{font-size:12px;color:var(--muted);margin:10px 0 4px;}
#orderFolderPanel .ofpSvcLinkRow{display:flex;align-items:center;gap:6px;font-size:12px;margin:3px 0;}
#orderFolderPanel .ofpSvcLinkName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#orderFolderPanel .ofpSvcLinkWhere{flex:0 0 auto;color:var(--muted);font-size:11px;}
#orderFolderPanel .ofpSvcLinked{display:flex;align-items:center;gap:8px;flex-wrap:wrap;font-size:11.5px;color:var(--muted);border:1px solid var(--line);border-radius:6px;padding:5px 8px;margin-bottom:8px;}
/* СО-патч 2026-09-29 — конец */
/* ===== Репорты №976/977/978/986/987 (2026-09-29, patch_beton.cjs) ===== */
/* №976: окно «Добавить испытание бетона» (поиск заказа Kenguru) */
.betonAddHint{font-size:12px;line-height:1.4;color:var(--muted);margin:0 0 8px;}
#betonAddList{display:flex;flex-direction:column;gap:6px;max-height:60vh;overflow:auto;}
.betonAddRow{display:flex;align-items:center;gap:10px;border:1px solid var(--line);border-radius:8px;padding:7px 10px;cursor:pointer;background:var(--bg);}
.betonAddRow:hover{background:var(--hover);}
.betonAddMain{flex:1 1 auto;min-width:0;font-size:13px;color:var(--text);}
.betonAddSub{font-size:11px;color:var(--muted);margin-top:2px;overflow-wrap:anywhere;}
.betonAddHas{color:#b45309;font-weight:600;}
html.theme-dark .betonAddHas{color:#fbbf24;}
.betonAddRow .btn{flex:0 0 auto;}
.betonAddEmpty{padding:18px;color:var(--muted);text-align:center;font-size:13px;}
#betonRegOvl h2{flex-wrap:nowrap;}   /* на ПК — одна строка: подзаголовок ужимается (многоточие), кнопки целиком */
#betonRegOvl h2>span:first-child{flex:0 0 auto;white-space:nowrap;}
#betonRegOvl h2>span+span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#betonRegOvl h2 .btn{flex:0 0 auto;white-space:nowrap;}
@media(max-width:600px){ #betonRegOvl h2{flex-wrap:wrap;} .betonAddRow{flex-wrap:wrap;} .betonAddRow .btn{width:100%;} }
/* №977/№978: пресеты класса бетона и «Монтаж 1 / Монтаж 2» — вид .betonCustSw (№171) */
.betonCustSw{flex-wrap:wrap;}
.betonCustSw .btn[disabled]{opacity:.5;cursor:default;}
/* №986: закреп документов в панели «Документы» — ПКМ-меню (как #ptoCtxMenu), булавка, приглушённый закрытый */
#dmDocCtxMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:180px;}
#dmDocCtxMenu.show{display:block;}
#dmDocCtxMenu button{display:block;width:100%;text-align:left;padding:7px 10px;border:none;background:none;
  cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
#dmDocCtxMenu button:hover{background:var(--hover);}
#dmDocCtxMenu .dmCtxHint{font-size:11px;color:var(--muted);padding:4px 10px 6px;max-width:220px;}
.dmRow .dmPinMark{display:inline-flex;vertical-align:-2px;margin-right:4px;color:var(--accent-d);}
.dmRow .dmPinMark svg{width:12px;height:12px;fill:currentColor;}
.dmRow.dmPinClosed{opacity:.55;}
.dmRow.dmPinClosed:hover{opacity:.85;}
.dmPinSubHd{font-size:10px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.3px;margin:2px 2px 0;}
/* №987: «Пользователи ▾» в окне «История изменений» */
#histUserBtn{flex:0 0 auto;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#histUserBtn.on{background:var(--accent-tint);border-color:var(--accent);color:var(--accent-d);font-weight:600;}
#histUserMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:230px;max-width:min(360px,calc(100vw - 8px));max-height:60vh;overflow:auto;}
#histUserMenu.show{display:block;}
#histUserMenu button{display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%;text-align:left;padding:7px 10px;
  border:none;background:none;cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
#histUserMenu button:hover{background:var(--hover);}
#histUserMenu button.cur{font-weight:700;color:var(--accent-d);}
#histUserMenu .humL{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
#histUserMenu .humN{flex:0 0 auto;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums;}
#histUserMenu .humSep{height:1px;background:var(--line);margin:4px 2px;}
#histUserMenu .humHint{font-size:11px;color:var(--muted);padding:4px 10px 6px;max-width:260px;}
/* CARD0929_START — репорты карточки заказа №974/975/983/984/985 (29.09.2026) */
/* №974: план/факт «с — по» */
.pfRange{display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;min-width:0;}
.pfRange .dpWrap,.pfRange>input[type=date]{flex:1 1 84px;min-width:84px;}
.pfRange .dpBtn{min-width:0;width:100%;padding:5px 6px;}
.pfDash{color:var(--muted);font-size:12px;flex:0 0 auto;}
.pfPlanRow .pfRange,.pfFactRow .pfRange{flex:1 1 196px;}   /* не влезает рядом с подписью — «с — по» целиком строкой ниже */
@media(max-width:600px){   /* телефон: «с — по» — отдельной строкой под подписью, поровну на всю ширину */
  .pfPlanRow .pfRange,.pfFactRow .pfRange{flex-basis:100%;}
  .pfRange .dpWrap,.pfRange>input[type=date]{flex:1 1 0;min-width:0;}
}
/* №975: операции «Папки заказа» — строка статуса, заглушки, плашка */
.ofpProg{margin:6px 0 4px;padding:6px 8px;border:1px solid var(--line);border-radius:6px;background:var(--row-alt,var(--bg));font-size:12px;}
.ofpProgTxt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:4px;}
.ofpProgBar{height:6px;border-radius:3px;background:var(--line);overflow:hidden;}
.ofpProgBar>i{display:block;height:100%;width:0;background:var(--accent);transition:width .25s;}
.ofpProgIndet .ofpProgBar>i{width:30%!important;animation:ofpIndet 1.1s linear infinite;}
@keyframes ofpIndet{0%{margin-left:-30%}100%{margin-left:100%}}
.ofpPend{display:flex;flex-direction:column;gap:2px;margin-bottom:4px;}
.ofpPendRow{display:grid;grid-template-columns:18px minmax(0,1fr) auto;gap:6px;align-items:center;font-size:12px;padding:4px 6px;border-radius:4px;background:var(--row-alt,var(--bg));color:var(--muted);}
.ofpPendNm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text);}
.ofpPend-ok{color:#16a34a;}
.ofpPend-err{color:#dc2626;}
#ofJobToast{position:fixed;left:50%;bottom:18px;transform:translateX(-50%);z-index:95;width:min(460px,calc(100vw - 32px));box-sizing:border-box;
  background:var(--panel);color:var(--text);border:1px solid var(--line);border-radius:8px;box-shadow:0 6px 20px rgba(0,0,0,.2);padding:8px 12px;font-size:12.5px;}
#ofJobToast .ofjtTxt{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:5px;}
@media(max-width:600px){#ofJobToast{bottom:auto;top:8px;}}   /* на телефоне внизу — кнопки карточки */
/* №983: документы — плитки сеткой (3–4 в ряд с переносом, на телефоне — по одной) */
.docList{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:8px;align-items:start;}
.docList>.cxempty{grid-column:1/-1;}
.docRow.docTile{display:flex;flex-direction:column;gap:6px;padding:8px 10px;min-width:0;}
.docTile .docRowHd{grid-template-columns:12px 18px minmax(0,1fr) auto;gap:6px;padding:0;}
.docTile .docLbl{font-weight:600;width:100%;box-sizing:border-box;text-overflow:ellipsis;}
.docTileRow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:6px;align-items:center;}
.docTile .dpWrap{display:block;width:100%;}
.docTile .dpBtn{min-width:0;width:100%;font-size:12px;padding:4px 7px;}
.docTile .docStage{width:100%;box-sizing:border-box;}
.docTile .docBetonSub{padding:0;gap:4px;}
.docTile .docHandoverRow,.docTile .docBetonRow{grid-template-columns:70px minmax(0,1fr) minmax(0,1fr);gap:6px;}
.docTile .docBetonRow .docBetonNum{grid-column:2/-1;}
.docTile .docDeps{padding:0;}
.docTile .docDepsInfo{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.docTileFoot{display:flex;align-items:center;gap:6px;padding-top:6px;border-top:1px dashed var(--line);}
.docTileFoot .docHolder{flex:1 1 auto;min-width:0;}
@media(max-width:600px){.docList{grid-template-columns:minmax(0,1fr);}}
/* №983: окно «Журнал передач»/«Связать» */
#docPopOvl .modal{width:clamp(320px,92vw,640px);}
#docPopOvl .docRowBody{border-top:0;padding:0;}
#docPopOvl .docDepsPanel{max-width:none;margin:0;}
#docPopOvl .docLogRow input[type=text],#docPopOvl .docLogForm input[type=text]:not(.dpBtn){font:inherit;font-size:12px;padding:4px 6px;border:1px solid var(--line);border-radius:4px;background:var(--bg);color:inherit;}
.docDepsHint{font-size:12px;color:var(--muted);margin-bottom:4px;}
@media(max-width:600px){
  #docPopOvl .docLogRow,#docPopOvl .docLogForm{grid-template-columns:minmax(0,1fr);}
  #docPopOvl .docLogRow>.btn,#docPopOvl .docLogForm>.btn{justify-self:end;}
  #docPopOvl .docLogRow{padding-bottom:6px;border-bottom:1px solid var(--line);}
}
/* №984: список типов с галочками (на телефоне — нижний лист) */
.docPickPop{position:fixed;z-index:1400;background:var(--panel);color:var(--text);border:1px solid var(--line);border-radius:8px;
  box-shadow:0 8px 24px rgba(0,0,0,.18);width:300px;max-width:calc(100vw - 16px);max-height:min(420px,70vh);display:flex;flex-direction:column;}
.docPickHd{display:flex;flex-wrap:wrap;align-items:center;gap:2px 8px;padding:8px 10px 6px;border-bottom:1px solid var(--line);font-size:12.5px;}
.docPickHd>b{flex:1 1 auto;}
.docPickHint{order:3;flex:1 1 100%;font-size:11px;color:var(--muted);}
.docPickList{overflow:auto;padding:4px 0;min-height:0;}
.docPickRow{display:flex;align-items:center;gap:8px;padding:5px 10px;font-size:13px;cursor:pointer;}
.docPickRow:hover{background:var(--row-alt,var(--bg));}
.docPickRow input{width:16px;height:16px;flex:0 0 auto;margin:0;cursor:pointer;}
.docPickName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.docPickN{font-size:11px;color:var(--muted);}
.docPickStd,.docDirStdRo{font-size:10.5px;color:#1d7a3d;background:#e1f5e6;border-radius:3px;padding:0 5px;white-space:nowrap;}
.docPickEmpty{font-size:12px;color:var(--muted);padding:8px 10px;}
.docPickOwn{font:inherit;font-size:12.5px;text-align:left;padding:8px 10px;border:0;border-top:1px solid var(--line);background:transparent;
  color:var(--accent-d,var(--accent));cursor:pointer;border-radius:0 0 8px 8px;}
.docPickOwn:hover{background:var(--row-alt,var(--bg));}
.docPickBack{position:fixed;inset:0;z-index:1399;background:rgba(32,33,36,.35);}
.docPickPop.docPickSheet{left:0!important;right:0;bottom:0;top:auto!important;width:auto;max-width:none;max-height:72vh;border-radius:12px 12px 0 0;
  padding-bottom:env(safe-area-inset-bottom);}
.docPickSheet .docPickRow{padding:10px 14px;font-size:15px;}
.docPickSheet .docPickRow input{width:20px;height:20px;}
.docPickSheet .docPickOwn{padding:12px 14px;font-size:14px;border-radius:0;}
html.theme-dark .docPickStd,html.theme-dark .docDirStdRo{background:#173425;color:#7fd89d;}
/* №985(б): отметка «типовой» в справочнике */
.docDirRow.docDirRowStd{grid-template-columns:minmax(0,1fr) auto auto;}
.docDirStd{display:flex;align-items:center;gap:4px;font-size:12px;color:var(--muted);cursor:pointer;white-space:nowrap;user-select:none;}
.docDirStd input{margin:0;}
/* CARD0929_END */
/* P989_START — №989: ПКМ-меню строки главной таблицы (вид как #ptoCtxMenu/#dmDocCtxMenu) */
#rowCtxMenu{position:fixed;z-index:70;background:var(--panel);border:1px solid var(--line);border-radius:8px;
  box-shadow:0 6px 20px rgba(0,0,0,.22);padding:4px;display:none;min-width:200px;max-width:min(320px,calc(100vw - 16px));}
#rowCtxMenu.show{display:block;}
#rowCtxMenu .rcmHead{font-size:11px;font-weight:700;color:var(--muted);padding:4px 10px 5px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
#rowCtxMenu button{display:block;width:100%;text-align:left;padding:7px 10px;border:none;background:none;
  cursor:pointer;font-size:13px;border-radius:6px;color:var(--text);}
#rowCtxMenu button:hover:not([disabled]),#rowCtxMenu button:focus-visible{background:var(--hover);outline:none;}
#rowCtxMenu button.danger{color:#dc2626;}
#rowCtxMenu button[disabled]{opacity:.45;cursor:default;}
#rowCtxMenu .rcmSep{height:1px;background:var(--line);margin:4px 2px;}
#rowCtxMenu .rcmHint{font-size:11px;line-height:1.35;color:var(--muted);padding:2px 10px 6px;}
html.theme-dark #rowCtxMenu button.danger{color:#f87171;}
#tbody tr.rcmOn td{box-shadow:inset 0 0 0 9999px rgba(26,115,232,.12);}
html.theme-dark #tbody tr.rcmOn td{box-shadow:inset 0 0 0 9999px rgba(66,133,244,.22);}
#tbody tr.rcmPress{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;}
@media(max-width:600px){
  #rowCtxMenu{min-width:220px;}
  #rowCtxMenu .rcmHead{font-size:12px;}
  #rowCtxMenu button{padding:11px 12px;font-size:15px;}
  #rowCtxMenu .rcmHint{font-size:12px;}
}
/* P989_END */

/* Report 1009: virtual rows mark passports absent from the order folder. */
#orderFolderPanel .ofPassportMissing{color:var(--muted);background:var(--bg);opacity:.72;cursor:default;border:1px dashed var(--line);}
#orderFolderPanel .ofPassportMissing:hover{background:var(--bg);}
#orderFolderPanel .ofPassportMissing .fsCellName{font-style:italic;}
